codeforces Round 593(div. 2)

Posted aya-uchida

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces Round 593(div. 2)相关的知识,希望对你有一定的参考价值。


A、Stones

题意:

给出三种石头分别$a$,$b$,$c$个,每次拿石头的时候只能拿$1$个第一种石头和$2$个第二种石头,或者$1$个第二种石头和$2$个第三种石头,求最多能拿到多少?

题解:

先考虑后一种方案:这样子一共拿了$min(b, c/2)*3$个石头,然后剩下的石头再取$min((b-c/2)/2,a)*3$.

AC代码:

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n;
 6     scanf("%d", &n);
 7     while (n--)
 8     {
 9         int a, b, c;
10         scanf("%d%d%d", &a, &b, &c);
11         int ans = 0;
12         while (b > 0 && c > 1)
13         {
14             ans += 3;
15             b -= 1;
16             c -= 2;
17         }
18         while (b > 1 && a > 0)
19         {
20             ans += 3;
21             b -= 2;
22             a -= 1;
23         }
24         printf("%d
", ans);
25     }
26     return 0;
27 }
View Code

B、Alice and the List of Presents

题意:

给出无限个$n$种东西放进$m$个包且每个包中不出现重复元素的方案数,包里面可以不放东西。

题解:

考虑每个包里面都可以放或者不放某东西,一共$2^m-1$种,然后一共有$n$个物品,所以就是$(2^m-1)^n$种。

AC代码:

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod = 1e9 + 7;
 5 ll pow(ll a, ll b, ll p)
 6 {
 7     ll res = 1;
 8     while (b)
 9     {
10         if (b & 1)
11             res = res * a % p;
12         a = a * a % p;
13         b >>= 1;
14     }
15     return res;
16 }
17 int main()
18 {
19     ll n, m;
20     scanf("%lld%lld", &n, &m);
21     printf("%lld", pow((pow(2, m, mod) - 1ll + mod) % mod, n, mod));
22     return 0;
23 }
View Code

C、Labs

题意:

定义$f(X,Y)$是$X$集合中$a$,和$Y$集合中的$b$满足$a>b$的数对的数量。给出一个$n imes n$的矩阵,元素是$1~n^2$,求出一种填数方式,使得对于所有的行,最大的$f(X_i,X_j)$最小。

题解:

考虑要最大的最小,首先发现因为所有的数都不一样,所以$f(X,Y)+f(Y,X)=n*n$,则我们需要找到一种分法,使得所有的行之间的$max(f(X,Y),f(Y,X))$等于$frac {n*n}{2}$。所以,我们可以把这$n*n$个数按顺序分成$n$组,然后就第一组选$max$,第二组选$min$,第三组选$max$交替选够$n$个数,构成第一行,然后第二行从$min$选起,交替选够$n$个数,以此类推,观察矩阵的数可以发现规律,按规律写出代码即可。

AC代码:

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 3e2 + 5;
 4 int ans[N][N];
 5 int main()
 6 {
 7     int n;
 8     scanf("%d", &n);
 9     for (int i = 1; i <= n; ++i)
10         for (int j = 1; j <= n; ++j)
11             ans[i][j] = i + n * (j - 1);
12     for (int i = 2; i <= n; i += 2)
13         for (int j = 1; j <= n / 2; ++j)
14             swap(ans[j][i], ans[n - j + 1][i]);
15     for (int i = 1; i <= n; ++i)
16         for (int j = 1; j <= n; ++j)
17             printf("%d%c", ans[i][j], " 
"[j == n]);
18     return 0;
19 }
View Code

D、Alice and the Doll

题意:

给出一个玩偶,它只能向前和向右,这个玩偶在$(1,1)$开始,走一个有障碍物的$n*m$的方格图,求能不能走完所有不是障碍物的格子。

题解:

理论上直接模拟就行,但是这样子时间复杂度是$O(n*m)$,所以我们预处理出每一行每一列所有障碍物,排好序,这样子就可以用二分查找找出前面的第一个障碍物。这样子时间就降到$O(nlogn)$了。

AC代码:

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 5;
 4 typedef long long ll;
 5 vector<int> G1[N];
 6 vector<int> G2[N];
 7 int main()
 8 {
 9     int n, m, k;
10     scanf("%d%d%d", &n, &m, &k);
11     for (int i = 1; i <= k; ++i)
12     {
13         int a, b;
14         scanf("%d%d", &a, &b);
15         G1[a].push_back(b);
16         G2[b].push_back(a);
17     }
18     for (int i = 1; i <= n; ++i)
19         sort(G1[i].begin(), G1[i].end());
20     for (int i = 1; i <= m; ++i)
21         sort(G2[i].begin(), G2[i].end());
22     bool f = 0;
23     ll ans = 1;
24     int x = 1, y = 1;
25     int up = 1, down = n, left = 1, right = m;
26     int dir = 0;
27     while (1)
28     {
29         int ny, nx;
30         if (dir == 0) //右方向
31         {
32             int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin();
33             nx = x;
34             if (pos == G1[x].size())
35                 ny = right;
36             else
37                 ny = min(right, G1[x][pos] - 1);
38             up = x + 1;
39         }
40         else if (dir == 1) //下方向
41         {
42             int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin();
43             ny = y;
44             if (pos == G2[y].size())
45                 nx = down;
46             else
47                 nx = min(down, G2[y][pos] - 1);
48             right = y - 1;
49         }
50         else if (dir == 2)
51         {
52             int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin() - 1;
53             nx = x;
54             if (pos < 0)
55                 ny = left;
56             else
57                 ny = max(left, G1[x][pos] + 1);
58             down = x - 1;
59         }
60         else if (dir == 3)
61         {
62             int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin() - 1;
63             ny = y;
64             if (pos < 0)
65                 nx = up;
66             else
67                 nx = max(up, G2[y][pos] + 1);
68             left = y + 1;
69         }
70         if (nx == x && ny == y && f)
71             break;
72         dir = (dir + 1) % 4;
73         ans += abs(nx - x) + abs(ny - y);
74         x = nx;
75         y = ny;
76         f = 1;
77     }
78     if (ans == (ll)n * m - k)
79         printf("Yes
");
80     else
81         printf("No
");
82     return 0;
83 }
View Code

E、Alice and the Unfair Game

题意:

题解:

AC代码:

 

以上是关于codeforces Round 593(div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #593 (Div. 2) C. Labs

Codeforces Round #593 (Div. 2) A. Stones

Codeforces Round #593 (Div. 2) B. Alice and the List of Presents

Codeforces Round #329 div2

codeforces #593 div2 ABCD 题解

D. Happy Tree Party CodeForces 593D树链剖分,树边权转点权