「题解」Educational Codeforces Round 170 (Rated for Div. 2)

before

AE 的题解

我不想写作业呜呜。

A. Two Screens

Problem

A. Two Screens

Sol&Code

理解题意后发现使用复制的方法完成最长公共前缀即可。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
#include <bits/stdc++.h> typedef long long ll; typedef std::pair<int, int> pii; int T; std::string s1, s2; int main() { scanf("%d", &T); while (T--) { std::cin >> s1 >> s2; int l1 = s1.length(), l2 = s2.length(); int now = 0; while (now < l1 && now < l2 && s1[now] == s2[now]) ++now; if (now) printf("%d\n", now + 1 + l1 - now + l2 - now); else printf("%d\n", l1 + l2); } return 0; }

B. Binomial Coefficients, Kind Of

Problem

B. Binomial Coefficients, Kind Of

Sol&Code

手推一部分数据不难发现答案是 2 的幂次。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
#include <bits/stdc++.h> #define N 100001 typedef long long ll; typedef std::pair<int, int> pii; int T, n[N], k[N]; const int mod = 1000000007; int qpow(int a, int b) { int ans = 1, base = a; while (b) { if (b & 1) ans = 1ll * ans * base % mod; base = 1ll * base * base % mod; b >>= 1; } return ans % mod; } int main() { scanf("%d", &T); for (int i = 1; i <= T; ++i) scanf("%d", &n[i]); for (int i = 1; i <= T; ++i) scanf("%d", &k[i]); for (int i = 1; i <= T; ++i) { if (k[i] == 0 || k[i] == n[i]) puts("1"); else printf("%d\n", qpow(2, k[i])); } return 0; }

C. New Game

Problem

C. New Game

Sol&Code

双指针维护一下从某个数字开始最多能到哪,注意之间有多少不同的数即可。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
#include <bits/stdc++.h> #define N 200001 typedef long long ll; typedef std::pair<int, int> pii; int T, n, k, a[N]; int main() { scanf("%d", &T); while (T--) { scanf("%d %d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); std::sort(a + 1, a + n + 1); int l = 1, r = 1, ans = 1, cnt_ = 1; while (r < n) { while (r < n && (a[r + 1] == a[r] || (a[r + 1] == a[r] + 1 && cnt_ < k)) ) { if (a[r + 1] == a[r]) ++r; else ++r, ++cnt_; } ans = std::max(ans, r - l + 1); if (r < n && a[r + 1] - a[r] > 1) ++r, l = r, cnt_ = 1; else { int gl = l; while (gl < n && a[gl] == a[l]) ++gl; l = gl, --cnt_; } } printf("%d\n", ans); } return 0; }

D. Attribute Checks

Problem

D. Attribute Checks

Sol&Code

fi,ji 个技能点,智力用了 j 个,最多能通过到 i+1 个技能点之前的几个测试。

转移,f[i][j] = max(f[i][j], max(f[i - 1][j], f[i - 1][j - 1]) + ad),其中 adj 点智力, ij 点力量能通过的第 i 个技能点和第 i+1 个技能点之间的测试的数量,可以用树状数组来做。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
#include <bits/stdc++.h> #define N 5001 #define M 2000002 #define lowbit(x) ((x) & (-x)) typedef long long ll; typedef std::pair<int, int> pii; int n, m, a[M], f[N][N]; struct BIT { int a[5001]; void add(int x, int k) { while (x <= m) a[x] += k, x += lowbit(x); } int query(int x, int res = 0) { if (x < 0) return res; while (x > 0) res += a[x], x -= lowbit(x); return res; } }b1, b2; int main() { f[0][0] = 0; scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); int lst = 0, now = 0, cnt = 1, ans = 0; while (a[now + 1] != 0) ++now; ++now, lst = now; while (now <= n) { while (now <= n && a[now + 1] != 0) ++now; if (a[now + 1] == 0) { // std::cout << lst << " " << now << '\n'; for (int i = lst + 1; i <= now; ++i) { if (a[i] > 0) b1.add(a[i], 1); else b2.add(-a[i], 1); } for (int i = 0; i <= cnt; ++i) { int a1 = b1.query(i), a2 = b2.query(cnt - i); f[cnt][i] = std::max(f[cnt][i], std::max(f[cnt - 1][i - 1], f[cnt - 1][i]) + a1 + a2); // std::cout <<a1 << " " << a2 << " " << cnt << " " << i << " " << f[cnt][i] << '\n'; } for (int i = lst + 1; i <= now; ++i) { if (a[i] > 0) b1.add(a[i], -1); else b2.add(-a[i], -1); } ++now, lst = now, ++cnt; } } for (int i = 0; i <= m; ++i) ans = std::max(ans, f[m][i]); printf("%d\n", ans); return 0; } /* 9 3 0 0 1 0 2 -3 -2 -2 1 */

E. Card Game

Problem

E. Card Game

Sol&Code

参考的官方题解

fi,j 表示前 i 行分完,并且两人进行游戏之后多出 j 张第一行的卡的方案数。

对于前 1 行,可以用动态规划做,gi,j 表示前 i 张(还是后 i 张?不是很重要),符合条件的多分给一个人 j 张的分法,转移就讨论分给谁转移即可。

对于后面的行,可以枚举之前剩下多少,分完某一行之后剩下多少之后转移即可,gi.j 会在转移中用到。

详细的看代码或者原题解吧。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
#include <bits/stdc++.h> #define N 505 typedef long long ll; typedef std::pair<int, int> pii; const int mod = 998244353; int n, m, g[N][N], f[N][N]; int main() { scanf("%d %d", &n, &m); g[0][0] = 1; for (int i = 1; i <= m; ++i) { for (int j = 0; j <= i; ++j) { g[i][j] = (1ll * g[i - 1][j + 1] + ((j - 1 >= 0) ? g[i - 1][j - 1] : 0)) % mod; } } for (int i = 0; i <= m; ++i) f[1][i] = g[m][i]; for (int i = 2; i <= n; ++i) { for (int j = 0; j <= m; ++j) { for (int j_ = 0; j_ <= j; ++j_) { f[i][j_] = (1ll * f[i][j_] + 1ll * f[i - 1][j] * g[m][j - j_] % mod) % mod; } } } printf("%d\n", f[n][0]); return 0; }

F. Choose Your Queries

Problem

F. Choose Your Queries

Sol&Code

参考的题解

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
#include <bits/stdc++.h> #define N 300001 typedef long long ll; typedef std::pair<int, int> pii; bool vis[N], used[N]; std::vector<pii> e[N]; int n, q, x[N], y[N], st[N], val[N]; void dfs(int u, int id) { vis[u] = true; for (auto [v, id_] : e[u]) { if (vis[v]) continue; dfs(v, id_); st[u] ^= st[v], st[v] ^= st[v]; } if (st[u] && id != 0) used[id] = true; } int main() { scanf("%d %d", &n, &q); for (int i = 1; i <= q; ++i) { scanf("%d %d", &x[i], &y[i]); e[x[i]].push_back({y[i], i}); e[y[i]].push_back({x[i], i}); st[x[i]] ^= 1; } for (int i = 1; i <= n; ++i) { if (!vis[i]) dfs(i, 0); } for (int i = 1; i <= q; ++i) { char c = 'x'; int p = x[i]; if (used[i]) c = 'y', p = y[i]; if (val[p]) --val[p], printf("%c-\n", c); else ++val[p], printf("%c+\n", c); } return 0; }

After

唉唉。。

好多作业。

不想上课。。

好久没打 cf 了,好多笨蛋错误,初始值错了两发,数组开小了一发。我是笨蛋。

C 和 D 写了好久,感觉不会写代码了。

posted @   yu__xuan  阅读(268)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开