Codeforces Round #533 (Div. 2) Solution

A. Salem and Sticks

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 1010
 5 int n, a[N];
 6
 7 int work(int x)
 8 {
 9     int res = 0;
10     for (int i = 1; i <= n; ++i)
11         res += max(0, abs(x - a[i]) - 1);
12     return res;
13 }
14
15 int main()
16 {
17     while (scanf("%d", &n) != EOF)
18     {
19         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
20         int Min = (int)1e9, pos = -1;
21         for (int i = 1; i <= 100; ++i)
22         {
23             int tmp = work(i);
24             if (tmp < Min)
25             {
26                 Min = tmp;
27                 pos = i;
28             }
29         }
30         printf("%d %d\n", pos, Min);
31     }
32     return 0;
33 }

B. Zuhair and Strings

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 200010
 5 int n, k;
 6 char s[N];
 7
 8 int work(char c)
 9 {
10     int res = 0;
11     int tmp = 0;
12     for (int i = 1; i <= n; ++i)
13     {
14         if (s[i] != c) tmp = 0;
15         else
16         {
17             ++tmp;
18             if (tmp == k)
19             {
20                 ++res;
21                 tmp = 0;
22             }
23         }
24     }
25     return res;
26 }
27
28 int main()
29 {
30     while (scanf("%d%d", &n, &k) != EOF)
31     {
32         scanf("%s", s + 1);
33         int res = 0;
34         for (int i = ‘a‘; i <= ‘z‘; ++i)
35             res = max(res, work(i));
36         printf("%d\n", res);
37     }
38     return 0;
39 }

C. Ayoub and Lost Array

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define ll long long
 5 #define N 200010
 6 const ll MOD = (ll)1e9 + 7;
 7 int n, l, r;
 8 ll a[3], f[N][3];
 9
10 int main()
11 {
12     while (scanf("%d%d%d", &n, &l, &r) != EOF)
13     {
14         memset(a, 0, sizeof a);
15         while (l % 3 && l <= r)
16         {
17             a[l % 3]++;
18             ++l;
19         }
20         while (r % 3 && l <= r)
21         {
22             a[r % 3]++;
23             --r;
24         }
25         if (l <= r)
26         {
27             ++a[0];
28             int tmp = (r - l) / 3;
29             a[0] += tmp;
30             a[1] += tmp;
31             a[2] += tmp;
32         }
33         memset(f, 0, sizeof f);
34         f[0][0] = 1;
35         for (int i = 1; i <= n; ++i)
36         {
37             f[i][0] = (f[i - 1][0] * a[0] % MOD + f[i - 1][1] * a[2] % MOD + f[i - 1][2] * a[1] % MOD) % MOD;
38             f[i][1] = (f[i - 1][0] * a[1] % MOD + f[i - 1][1] * a[0] % MOD + f[i - 1][2] * a[2] % MOD) % MOD;
39             f[i][2] = (f[i - 1][0] * a[2] % MOD + f[i - 1][1] * a[1] % MOD + f[i - 1][2] * a[0] % MOD) % MOD;
40         }
41         printf("%lld\n", f[n][0]);
42     }
43     return 0;
44 }

D. Kilani and the Game

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 1010
 5 int n, m, p;
 6 char G[N][N];
 7 int s[10];
 8 struct node
 9 {
10     int x, y, step;
11     node () {}
12     node (int x, int y, int step) : x(x), y(y), step(step) {}
13 };
14 queue <node> q[10];
15 bool stop()
16 {
17     for (int i = 1; i <= p; ++i) if (!q[i].empty())
18         return false;
19     return true;
20 }
21
22 int Move[][2] =
23 {
24     -1, 0,
25      1, 0,
26      0,-1,
27      0, 1,
28 };
29 bool ok(int x, int y)
30 {
31     if (x < 1 || x > n || y < 1 || y > m || G[x][y] != ‘.‘) return false;
32     return true;
33 }
34
35 void BFS(int id, int cnt)
36 {
37     while (!q[id].empty())
38     {
39         int x = q[id].front().x;
40         int y = q[id].front().y;
41         int step = q[id].front().step;
42         //printf("%d %d %d %d\n", x, y, id, step);
43         if (step / s[id] >= cnt) return;
44         q[id].pop();
45         for (int i = 0; i < 4; ++i)
46         {
47             int nx = x + Move[i][0];
48             int ny = y + Move[i][1];
49             if (ok(nx, ny))
50             {
51                 G[nx][ny] = id + ‘0‘;
52                 q[id].push(node(nx, ny, step + 1));
53             }
54         }
55     }
56 }
57
58 int main()
59 {
60     while (scanf("%d%d%d", &n, &m, &p) != EOF)
61     {
62         for (int i = 1; i <= p; ++i) scanf("%d", s + i);
63         for (int i = 1; i <= n; ++i) scanf("%s", G[i] + 1);
64         for (int i = 1; i <= p; ++i) while (!q[i].empty()) q[i].pop();
65         for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (isdigit(G[i][j]))
66             q[G[i][j] - ‘0‘].push(node(i, j, 0));
67         int cnt = 1;
68         while (1)
69         {
70             for (int i = 1; i <= p; ++i) BFS(i, cnt);
71             ++cnt;
72             if (stop()) break;
73         }
74         int ans[10];
75         memset(ans, 0, sizeof ans);
76         for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (isdigit(G[i][j]))
77             ++ans[G[i][j] - ‘0‘];
78         //for (int i = 1; i <= n; ++i) printf("%s\n", G[i] + 1);
79         for (int i = 1; i <= p; ++i) printf("%d%c", ans[i], " \n"[i == p]);
80     }
81     return 0;
82 }

E. Helping Hiasat

Upsolved.

题意:

两种操作

  • 更改自己的handle
  • 伙伴查询handle

如果一个伙伴在每次查询时显示的都是自己名字,那么他就会开心

问 最多可以让多少人开心

思路:

法一:

一张图的最大独立集是选出一个点集,使得任意两点不相邻

一张图的最大团是选出一个点集,使得任意两点之间有边相连

一张无向图的补图的最大图就是原图的最大独立集

我们发现这道题两个1之间的所有点都是不能一起happy的,那我们给他们两两之间连上边

然后求补图的最大团即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 110
 5 int n, m, t;
 6 int g[N][N];
 7 int dp[N];
 8 int stk[N][N];
 9 int mx;
10
11 map <string, int> mp;
12 int get(string s)
13 {
14     if (mp.find(s) != mp.end()) return mp[s];
15     else mp[s] = t++;
16     return mp[s];
17 }
18
19 int DFS(int n, int ns, int dep)
20 {
21     if (ns == 0)
22     {
23         mx = max(mx, dep);
24         return 1;
25     }
26     int i, j, k, p, cnt;
27     for (i = 0; i < ns; ++i)
28     {
29         k = stk[dep][i];
30         cnt = 0;
31         if (dep + n - k <= mx)
32             return 0;
33         if (dep + dp[k] <= mx)
34             return 0;
35         for (j = i + 1; j < ns; ++j)
36         {
37             p = stk[dep][j];
38             if (g[k][p])
39                 stk[dep + 1][cnt++] = p;
40         }
41         DFS(n, cnt, dep + 1);
42     }
43     return 1;
44 }
45
46 int clique(int n)
47 {
48     int i, j, ns;
49     for (mx = 0, i = n - 1; i >= 0; --i)
50     {
51         for (ns = 0, j = i + 1; j < n; ++j)
52         {
53             if (g[i][j])
54                 stk[1][ns++] = j;
55         }
56         DFS(n, ns, 1);
57         dp[i] = mx;
58     }
59     return mx;
60 }
61
62 vector <int> vec;
63 void add()
64 {
65     vec.erase(unique(vec.begin(), vec.end()), vec.end());
66     for (auto u : vec) for (auto v : vec)
67         g[u][v] = g[v][u] = 0;
68     vec.clear();
69 }
70
71 int main()
72 {
73     while (scanf("%d%d", &n, &m) != EOF)
74     {
75         t = 0;
76         mp.clear();
77         for (int i = 0; i < m; ++i) for (int j = 0; j < m; ++j) g[i][j] = 1;
78         []()
79         {
80             int op; char s[50];
81             for (int nn = 1; nn <= n; ++nn)
82             {
83                 scanf("%d", &op);
84                 if (op == 1)
85                     add();
86                 else
87                 {
88                     scanf("%s", s + 1);
89                     vec.push_back(get(s + 1));
90                 }
91             }
92         }();
93         add();
94         for (int i = 0; i < m; ++i) g[i][i] = 1;
95         //for (int i = 1; i <= m; ++i) for (int j = 1; j <= m; ++j) printf("%d %d %d\n", i, j, g[i][j]);
96         printf("%d\n", clique(m));
97     }
98     return 0;
99 }

法二:

$m = 40, 可以折半状压,再合起来$

考虑妆压的时候要从子集转移到超集,可以通过$dp上去$

$vp的时候想到折半状压,但是当时是枚举子集来转移,复杂度大大增加..$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 50
 5 #define M 1100010
 6 int n, m, t;
 7 int G[N][N];
 8
 9 map <string, int> mp;
10 int get(string s)
11 {
12     if (mp.find(s) != mp.end()) return mp[s];
13     else mp[s] = ++t;
14     return mp[s];
15 }
16
17 vector <int> vec;
18 void add()
19 {
20     vec.erase(unique(vec.begin(), vec.end()), vec.end());
21     for (auto u : vec) for (auto v : vec)
22         G[u][v] = 1;
23     vec.clear();
24 }
25
26 int f[M], g[M];
27 int main()
28 {
29     while (scanf("%d%d", &n, &m) != EOF)
30     {
31         t = 0; mp.clear();
32         memset(G, 0, sizeof G);
33         int op; char s[N];
34         for (int nn = 1; nn <= n; ++nn)
35         {
36             scanf("%d", &op);
37             if (op == 1) add();
38             else
39             {
40                 scanf("%s", s + 1);
41                 vec.push_back(get(s + 1));
42             }
43         }
44         add();
45         for (int i = 1; i <= m; ++i)
46             G[i][i] = 0;
47         int s1 = m / 2, s2 = m - s1;
48         for (int i = 1; i < (1 << s1); i <<= 1) f[i] = 1;
49         for (int i = 1; i < (1 << s2); i <<= 1) g[i] = 1;
50         f[0] = g[0] = 0;
51         for (int i = 1; i < (1 << s1); ++i)
52         {
53             for (int j = 0; j < s1; ++j) if (!((i >> j) & 1))
54             {
55                 int flag = 1;
56                 for (int k = 0; k < s1; ++k) if (((i >> k) & 1) && G[k + 1][j + 1])
57                 {
58                     flag = 0;
59                     break;
60                 }
61                 f[i | (1 << j)] = max(f[i | (1 << j)], f[i] + flag);
62             }
63         }
64         for (int i = 1; i < (1 << s2); ++i)
65         {
66             for (int j = 0; j < s2; ++j) if (!((i >> j) & 1))
67             {
68                 int flag = 1;
69                 for (int k = 0; k < s2; ++k) if (((i >> k) & 1) && G[s1 + k + 1][s1 + j + 1])
70                 {
71                     flag = 0;
72                     break;
73                 }
74                 g[i | (1 << j)] = max(g[i | (1 << j)], g[i] + flag);
75             }
76         }
77         int res = 0;
78         for (int i = 0; i < (1 << s1); ++i)
79         {
80             int s3 = (1 << s2) - 1;
81             for (int j = 0; j < s1; ++j) if ((i >> j) & 1)
82             {
83                 for (int k = 0; k < s2; ++k) if (G[j + 1][s1 + k + 1] && ((s3 >> k) & 1))
84                     s3 ^= (1 << k);
85             }
86             res = max(res, f[i] + g[s3]);
87         }
88         printf("%d\n", res);
89     }
90     return 0;
91 }

原文地址:https://www.cnblogs.com/Dup4/p/10342214.html

时间: 2024-07-30 07:20:22

Codeforces Round #533 (Div. 2) Solution的相关文章

Codeforces Round #275 (Div.1) Solution

好久没做题了,开场Virtual热热身. A 构造,我的方法是,取1,2,3...,k这几个差值,前k+1个数分别是 1, k+1, 2, k, ...., 之后就k+2, k+3, ..., n B 因为题设是与操作.我们按照每一位来,如果有一个限制某位是1,则将那段区间标志1,没有限制的位全部置零即可,然后检验为0的位是否全是1.标志一段区间可以用标记法,检验可以求和看差值. C 我做完之后看了CF tutorial 跟我的做法不同.我的做法比他给的复杂度低一点,不过题解好帅,而且跑出来速度

Codeforces Round #282 (Div.1) Solution

上午考试,下去去参观教堂,回来睡大觉,搞到现在才有时间做,水平恢复中. A 倒过来扫括号匹配很容易理解 B dp[i]表示最后一个拿到i的数目,sum[i]表示前i项dp和,sum2[i]表示前i项sum和.显然.dp[i]=sum2[o], o是最右边的坐标使得s[o+1,i]能包含t. C Interesting,我建了个树,硬着dp搞得..还没优化就46ms,想来这种题数据也不好构造. D Editorial似乎说离线搞,不过我在线搞出来了.我存了每个节点子树平方和,子树和,整体和,整体平

Codeforces Round #533 (Div. 2) D. Kilani and the Game(BFS)

题目链接:https://codeforces.com/contest/1105/problem/D 题意:p 个人在 n * m 的地图上扩展自己的城堡范围,每次最多走 a_i 步(曼哈顿距离),按 1 ~ p 的顺序,问最后每个人占领的点的数量. 题解:用一个队列维护当前起点,用另一个队列模拟当前起点走 a_i 步可以到达的全部点.(60 ~ 63行关键代码,多源bfs,不可分开跑) 数据: 4 3 2 2 1 1.. 1.. ..2 ... output:10 2 1 #include <

Codeforces Round #533 (Div. 2) B. Zuhair and Strings 【模拟】

传送门:http://codeforces.com/contest/1105/problem/B B. Zuhair and Strings time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Given a string ss of length nn and integer kk (1≤k≤n1≤k≤n). The string

[比赛] Codeforces Round #538 (Div. 2) solution (贪心,数学其他,二分,线段树)

已经写了100篇题解啦! link solution pdf #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read(){ int f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c

Codeforces Round #607 (Div. 1) Solution

从这里开始 比赛目录 我又不太会 div 1 A? 我菜爆了... Problem A Cut and Paste 暴力模拟一下. Code #include <bits/stdc++.h> using namespace std; typedef bool boolean; const int N = 1e6 + 5; const int Mod = 1e9 + 7; int T; int x; int len; char s[N]; int paste(int s1, int t1, in

Codeforces Round #268 (Div. 1) solution

A.24 Game 题意:给你1, 2, ..., n-1, n 这个序列,每次你可以取出两个数做+/-/*三种操作之一,然后把结果放回到序列中,询问能否是的这个序列最后只剩下一个24. 解法:首先很明显n < 4的时候是无解的.如果n=4,那么1 * 2 * 3 * 4=24,如果n=5,那么(5 - 1 - 2) * 3 * 4 = 24.若n > 5,那么我可以做n - (n - 1) = 1,相当于变成了n-2时候的情况加一个1,那么显然最后让答案乘上这个1即可. 代码: includ

Codeforces Round #276 (Div.1) Solution

水平越来越菜了 A  水题,注意后面全是1的情况 B  调和级数呀.把倍数全部扫一遍.一个数是多个数的倍数的话肯定是大的比较优.然后可以用two pointer扫一下. C  就是一个置换群,把轮换找出来就好了.傻逼的写了好久. D  有意思的傻逼DP,容易得到dp[i] = max{dp[j] + max{abs(a[k]-a[h])}} .只要更新一个U = max{a[i] + max_{0~(i-1)}{dp[i]}}和D = max{-a[i] + max_{0~(i-1)}{dp[i

Codeforces Round #283 (Div.1) Solution

A 贪心,从第一列开始一旦有不符合就把这列去掉.因为如果符合只可能使后面优势更大. B 枚举t就能找到局面了.因为调和级数的和是logn所以复杂度符合要求. C 将actor和part一起排好序,L小先,R大先,actor先.容易发现排在某个part后面的actor是不可能包含它的.它之后的part对于前面出现actor的L没有要求,于是每个part要尽量节约的使用R,于是找比自己R大最小的.set维护即可. D 题意是两个多边形围绕自己中心同样的角速度顺时针转,问有没有可能撞到.一眼就想到可以