[关闭]
@Dmaxiya 2020-12-12T15:19:20.000000Z 字数 6906 阅读 1085

Educational Codeforces Round 48

Codeforces


Contests 链接:Educational Codeforces Round 48
过题数:4
排名:269/7643

A. Death Note

题意

有一本死亡笔记,这本死亡笔记有无穷多页,每一页能够写下 行名字,死亡笔记要求从第 天到第 天,每天都要在笔记本上写下 行名字,死亡笔记只有在写到最后一行的时候才会翻页,问第 天会翻多少页。

输入

第一行包含两个整数 ,第二行为 个整数

输出

输出 个整数 表示第 天翻页的次数。

样例

输入 输出 提示
3 5
3 7 9
0 2 1 死亡笔记上每一页的名字为:
每一个中括号的内容是每一页的名字,其中的数字 表示第 天需要写下的名字。
4 20
10 9 19 2
0 0 1 1
1 100
99
0

题解

记录写的行数,按照题意模拟。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. LL n, m, now, cnt, page;
  21. int main() {
  22. #ifdef Dmaxiya
  23. freopen("test.txt", "r", stdin);
  24. // freopen("out.txt", "w", stdout);
  25. #endif // Dmaxiya
  26. ios::sync_with_stdio(false);
  27. while(scanf("%I64d%I64d", &n, &m) != EOF) {
  28. now = 0;
  29. for(int i = 1; i <= n; ++i) {
  30. if(i != 1) {
  31. printf(" ");
  32. }
  33. scanf("%I64d", &page);
  34. if(page >= m - now) {
  35. page -= m - now;
  36. printf("%I64d", page / m + 1);
  37. now = page % m;
  38. } else {
  39. now += page;
  40. printf("0");
  41. }
  42. }
  43. printf("\n");
  44. }
  45. return 0;
  46. }

B. Segment Occurrences

题意

给定两个字符串:长度为 串和长度为 串,有 次询问,每次询问一个区间 ,表示询问在 串的 子串内, 字符串在这个子串内出现的次数,下标从 开始。

输入

第一行包含 个整数 ,第二行为一个长度为 的字符串 ,第三行为一个长度为 的字符串 ,字符串 都只包含小写字母,接下去 行每行两个整数

输出

对于每次询问都输出一个答案。

样例

输入 输出 提示
10 3 4
codeforces
for
1 3
3 10
5 6
5 7
0
1
0
1
三次询问的子串分别为 "cod", "deforces", "fo" 和 "for"。
15 2 3
abacabadabacaba
ba
1 15
3 4
2 14
4
0
3
3 5 2
aaa
baaab
1 3
1 1
0
0

题解

预处理所有区间 内的答案, 输出。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 1000 + 100;
  21. int n, m, q, l, r;
  22. int ans[maxn][maxn];
  23. int Next[maxn];
  24. char str1[maxn], str2[maxn];
  25. void get_next(char *s) {
  26. Next[1] = 0;
  27. int j = 0;
  28. for(int i = 2; s[i]; ++i) {
  29. while(j > 0 && s[i] != s[j + 1]) {
  30. j = Next[j];
  31. }
  32. if(s[i] == s[j + 1]) {
  33. ++j;
  34. }
  35. Next[i] = j;
  36. }
  37. }
  38. int main() {
  39. #ifdef Dmaxiya
  40. freopen("test.txt", "r", stdin);
  41. // freopen("out.txt", "w", stdout);
  42. #endif // Dmaxiya
  43. ios::sync_with_stdio(false);
  44. while(scanf("%d%d%d", &n, &m, &q) != EOF) {
  45. scanf("%s%s", str1 + 1, str2 + 1);
  46. get_next(str2);
  47. for(int i = 1; i <= n; ++i) {
  48. int j = 0;
  49. int ret = 0;
  50. for(int ii = i; str1[ii]; ++ii) {
  51. while(j > 0 && str1[ii] != str2[j + 1]) {
  52. j = Next[j];
  53. }
  54. if(str1[ii] == str2[j + 1]) {
  55. ++j;
  56. }
  57. if(str2[j + 1] == '\0') {
  58. ++ret;
  59. j = Next[j];
  60. }
  61. ans[i][ii] = ret;
  62. }
  63. }
  64. while(q--) {
  65. scanf("%d%d", &l, &r);
  66. printf("%d\n", ans[l][r]);
  67. }
  68. }
  69. return 0;
  70. }

C. Vasya And The Mushrooms

题意

在一个 的网格内,每一格都有一个蘑菇,第一行第 格内的蘑菇每分钟长大 ,第二行第 格内的蘑菇每分钟长大 从第 行第 列的网格开始走起,每分钟都只能往相邻网格内移动,每一格蘑菇都必须经过一次(不能多于一次),最后不必回到初始位置,问如何规划路线才能使 收获的蘑菇最多。

输入

第一行包含一个整数 ,第二行为 个整数 ,第三行为 个整数 ,其中

输出

输出最大能够收获的蘑菇数量。

样例

输入 输出 提示
3
1 2 3
6 5 4
70 最优的路线如下:



最后收获的蘑菇为:
3
1 1000 10000
10 100 100000
543210 最优的路线如下:



最后收获的蘑菇为:

题解

由于每个网格都必须经过一次,所以从左上角开始的路线只有两类:“” 折返以及在某一次往右时停止折返,一直往右直到最后一格,然后返回,一般的情况如下(也可能在第二行一直往右,到最后从第一行返回):

rV6mMd.jpg

因此就是枚举中断往返开始一直往右的点,取最大值,在枚举中间点的时候,每次都需要 地求出贡献,首先用 预处理出 “” 走法的每个点的系数(从左上角点按照“下上右”的顺序 就可以得到):

rV63i8.jpg

然后从右往左递推一下后半段(先往右到最后,再往左回来的部分)的贡献,首先假设到某个点 的时候的系数为 ,则后面接着所有点的系数为:

rV6sWF.jpg

继续算从第 个点开始右转的贡献:

rV6ho6.jpg

其中 为第 个点上面第二张系数图中对应的系数,对比上一张系数图可以发现,从第 列到第 列所有的系数贡献都减 ,而从第 到第 列的贡献需要根据 的位置进行计算,因此就可以从 递推得到从任何一列开始右转的贡献,最终 地枚举转折点取最大值就能得到答案。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 300000 + 100;
  21. int n;
  22. bool vis[2][maxn];
  23. LL num[2][maxn], c[2][maxn], L[2][maxn], R[2][maxn];
  24. LL sum[maxn];
  25. const int dir[3][2] = {1, 0, -1, 0, 0, 1};
  26. bool in(int x, int y) {
  27. return x >= 0 && x < 2 && y >= 0 && y < n;
  28. }
  29. void dfs(int x, int y, LL cc) {
  30. vis[x][y] = true;
  31. c[x][y] = cc;
  32. for(int i = 0; i < 3; ++i) {
  33. int xx = x + dir[i][0];
  34. int yy = y + dir[i][1];
  35. if(in(xx, yy) && !vis[xx][yy]) {
  36. L[xx][yy] = L[x][y] + cc * num[x][y];
  37. dfs(xx, yy, cc + 1);
  38. }
  39. }
  40. }
  41. int main() {
  42. #ifdef Dmaxiya
  43. freopen("test.txt", "r", stdin);
  44. // freopen("out.txt", "w", stdout);
  45. #endif // Dmaxiya
  46. ios::sync_with_stdio(false);
  47. while(scanf("%d", &n) != EOF) {
  48. memset(sum, 0, sizeof(sum));
  49. for(int i = 0; i < 2; ++i) {
  50. for(int j = 0; j < n; ++j) {
  51. scanf("%I64d", &num[i][j]);
  52. sum[j] += num[i][j];
  53. vis[i][j] = false;
  54. R[i][j] = 0;
  55. }
  56. }
  57. for(int i = n - 2; i >= 0; --i) {
  58. sum[i] += sum[i + 1];
  59. }
  60. dfs(0, 0, 0);
  61. int Begin_up, Begin_down;
  62. if(n % 2 == 0) {
  63. Begin_up = n - 2;
  64. LL cc = c[0][n - 2];
  65. R[0][n - 2] = cc * num[0][n - 2] + (cc + 1) * num[0][n - 1] + (cc + 2) * num[1][n - 1] + (cc + 3) * num[1][n - 2];
  66. Begin_down = n - 1;
  67. cc = c[1][n - 1];
  68. R[1][n - 1] = cc * num[1][n - 1] + (cc + 1) * num[0][n - 1];
  69. } else {
  70. Begin_up = n - 1;
  71. LL cc = c[0][n - 1];
  72. R[0][n - 1] = cc * num[0][n - 1] + (cc + 1) * num[1][n - 1];
  73. Begin_down = n - 2;
  74. cc = c[1][n - 2];
  75. R[1][n - 2] = cc * num[1][n - 2] + (cc + 1) * num[1][n - 1] + (cc + 2) * num[0][n - 1] + (cc + 3) * num[0][n - 2];
  76. }
  77. for(int i = Begin_up; i - 2 >= 0; i -= 2) {
  78. LL cc = c[0][i - 2];
  79. R[0][i - 2] = R[0][i] - sum[i] * 2;
  80. R[0][i - 2] += cc * num[0][i - 2] + (cc + 1) * num[0][i - 1];
  81. cc += (n - i) * 2 + 2;
  82. R[0][i - 2] += cc * num[1][i - 1] + (cc + 1) * num[1][i - 2];
  83. }
  84. for(int i = Begin_down; i - 2 >= 0; i -= 2) {
  85. LL cc = c[1][i - 2];
  86. R[1][i - 2] = R[1][i] - sum[i] * 2;
  87. R[1][i - 2] += cc * num[1][i - 2] + (cc + 1) * num[1][i - 1];
  88. cc += (n - i) * 2 + 2;
  89. R[1][i - 2] += cc * num[0][i - 1] + (cc + 1) * num[0][i - 2];
  90. }
  91. LL aans = 0;
  92. for(int i = 0; i < 2; ++i) {
  93. for(int j = 0; j < n; ++j) {
  94. if((i + j) % 2 == 0) {
  95. aans = max(aans, L[i][j] + R[i][j]);
  96. }
  97. }
  98. }
  99. printf("%I64d\n", aans);
  100. }
  101. return 0;
  102. }

D. Vasya And The Matrix

题意

构造一个 列的矩阵,要求构造矩阵的每一行的异或值为 ,每一列的异或值为

输入

第一行包含两个整数 ,第二行有 个整数 ,第三行有 个整数

输出

如果可以构造出满足条件的矩阵,第一行输出一个 ,接着输出一个 的矩阵,要求矩阵的每一格元素 ,否则输出

样例

输入 输出
2 3
2 9
5 3 13
YES
3 4 5
6 7 8
3 3
1 7 6
2 15 12
NO

题解

列都填 ,最后一行的前 列分别填上 ,最后一列的前 行分别填上 ,最后根据异或的运算规则,分别从行和列的异或结果计算出第 行第 列的值,如果两次计算得到的值相等,则可以构造出满足条件的矩阵,否则输出

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 100 + 100;
  21. int n, m;
  22. int a[maxn], b[maxn];
  23. int ans[maxn][maxn];
  24. int main() {
  25. #ifdef LOCAL
  26. freopen("test.txt", "r", stdin);
  27. // freopen("out.txt", "w", stdout);
  28. #endif // LOCAL
  29. ios::sync_with_stdio(false);
  30. while(scanf("%d%d", &n, &m) != EOF) {
  31. for(int i = 1; i < n; ++i) {
  32. for(int j = 1; j < m; ++j) {
  33. ans[i][j] = 0;
  34. }
  35. }
  36. for(int i = 1; i <= n; ++i) {
  37. scanf("%d", a + i);
  38. ans[i][m] = a[i];
  39. }
  40. for(int i = 1; i <= m; ++i) {
  41. scanf("%d", b + i);
  42. ans[n][i] = b[i];
  43. }
  44. int tmp = 0;
  45. for(int i = 1; i < n; ++i) {
  46. tmp ^= ans[i][m];
  47. }
  48. ans[n][m] = tmp ^ ans[n][m];
  49. tmp = 0;
  50. for(int i = 1; i <= m; ++i) {
  51. tmp ^= ans[n][i];
  52. }
  53. if(tmp == a[n]) {
  54. printf("YES\n");
  55. for(int i = 1; i <= n; ++i) {
  56. for(int j = 1; j <= m; ++j) {
  57. if(j != 1) {
  58. printf(" ");
  59. }
  60. printf("%d", ans[i][j]);
  61. }
  62. printf("\n");
  63. }
  64. } else {
  65. printf("NO\n");
  66. }
  67. }
  68. return 0;
  69. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注