当前位置:   article > 正文

Codeforces Round #828 (Div. 3) 题解(A-E2)_828 codeforces

828 codeforces
Codeforces Round #828 (Div. 3)  这场难度在div3中感觉相对较高,题的质量是不错的,有学习价值。

A Number Replacement

思路:注意到a[i]=a[j]时必须有s[i]=s[j],而数据规模很小。因此O(n^2)暴搜解决。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void solve() {
  4. int n;
  5. cin >> n;
  6. int a[100];
  7. char b[100];
  8. for (int i = 0; i < n; i++)
  9. cin >> a[i];
  10. cin >> b;
  11. for (int i = 0; i < n; i++) {
  12. for (int j = i + 1; j < n; j++) {
  13. if (a[i] != a[j])
  14. continue;
  15. if (b[i] != b[j]) {
  16. cout << "NO" << endl;
  17. return;
  18. }
  19. }
  20. }
  21. cout << "YES" << endl;
  22. return;
  23. }
  24. int main() {
  25. int n;
  26. cin >> n;
  27. while (n--) {
  28. solve();
  29. }
  30. return 0;
  31. }

B Even-Odd Increments

思路:将偶数和奇数分开考虑,分别储存偶数之和、偶数个数、奇数之和、奇数个数。对于每一次操作,如果新增的x是偶数,则原奇偶性不变,如果新增的x是奇数,则改变奇偶性。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void solve() {
  4. long long n, q, op, tp;
  5. long long sum1 = 0, sum2 = 0, cou1 = 0, cou2 = 0;
  6. cin >> n >> q;
  7. for (int i = 0; i < n; i++) {
  8. cin >> tp;
  9. if (tp % 2) {
  10. sum1 += tp;
  11. cou1++;
  12. } else {
  13. sum2 += tp;
  14. cou2++;
  15. }
  16. }
  17. for (int i = 0; i < q; i++) {
  18. cin >> op >> tp;
  19. if (op == 0) {
  20. sum2 += cou2 * tp;
  21. if (tp % 2) {
  22. sum1 += sum2;
  23. cou1 += cou2;
  24. sum2 = 0;
  25. cou2 = 0;
  26. }
  27. } else {
  28. sum1 += cou1 * tp;
  29. if (tp % 2) {
  30. sum2 += sum1;
  31. cou2 += cou1;
  32. sum1 = 0;
  33. cou1 = 0;
  34. }
  35. }
  36. cout << sum1 + sum2 << endl;
  37. }
  38. return;
  39. }
  40. int main() {
  41. int n;
  42. cin >> n;
  43. while (n--) {
  44. solve();
  45. }
  46. return 0;
  47. }

C Traffic Light

思路:需要找到对应颜色和后面第一个Green之间距离差值的最大值。注意到红绿灯是循环的,因此O(n)扫两个循环节即可。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void solve() {
  4. int n;
  5. char c;
  6. cin >> n >> c;
  7. string s;
  8. cin >> s;
  9. if (c == 'g') {
  10. cout << 0 << endl;
  11. return;
  12. }
  13. int maxm = 0;
  14. int flag = 0, bj;
  15. for (int i = 0; i < 2 * n; i++) {
  16. int q = i % n;
  17. if (flag == 0 && s[q] == c) {
  18. flag = 1;
  19. bj = i;
  20. continue;
  21. }
  22. if (flag == 1 && s[q] == 'g') {
  23. flag = 0;
  24. if (i - bj > maxm)
  25. maxm = i - bj;
  26. }
  27. }
  28. cout << maxm << endl;
  29. return;
  30. }
  31. int main() {
  32. int n;
  33. cin >> n;
  34. while (n--) {
  35. solve();
  36. }
  37. return 0;
  38. }

D Divisibility by 2^n

思路:此题因注意到输入的数据是没用的,有用的仅仅是输入数据中有多少个2因子。先将2因子的数量统计出来,然后判断我们缺少了多少个2因子。

那缺少的2因子需要多少步操作得到呢?注意到,对于每个n=2^k的倍数,都具有k个2因子。因此我们统计含i个2因子的数的数量存在数组eys[i]中,然后模拟具体情况解决。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void solve() {
  4. int n, tp, eyz = 0;
  5. int eys[100];
  6. scanf("%d", &n);
  7. for (int i = 1; i <= n; i++) {
  8. scanf("%d", &tp);
  9. if (eyz >= n)
  10. continue;
  11. while (tp % 2 == 0) {
  12. tp /= 2;
  13. eyz++;
  14. }
  15. }
  16. if (eyz >= n) {
  17. cout << 0 << endl;
  18. return;
  19. }
  20. int cz = n - eyz, sum = 0, cou = 0;
  21. int j = 1;
  22. for (int i = 2; i <= n; i *= 2) {
  23. eys[j] = n / i;
  24. j++;
  25. }
  26. for (int p = 1; p < j - 1; p++) {
  27. eys[p] -= eys[p + 1];
  28. }
  29. for (int p = j - 1; p >= 1; p--) {
  30. if (sum + eys[p]*p < cz) {
  31. sum += eys[p] * p;
  32. cou += eys[p];
  33. continue;
  34. } else {
  35. cou += (cz - sum) / p;
  36. if ((cz - sum) % p != 0)
  37. cou++;
  38. cout << cou << endl;
  39. return;
  40. }
  41. }
  42. cout << -1 << endl;
  43. return;
  44. }
  45. int main() {
  46. int n;
  47. cin >> n;
  48. while (n--) {
  49. solve();
  50. }
  51. return 0;
  52. }

E1 - Divisible Numbers(easy version)

思路:将x从a+1到c遍历一遍,对于每个x,我们只需要找出是否存在一个[b+1,d]中的y满足x*y整除a*b。而x*y整除a*b可以化为y整除a*b/gcd(a*b,x)。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void solve() {
  4. long long a, b, c, d;
  5. cin >> a >> b >> c >> d;
  6. for (long long i = a + 1; i <= c; i++) {
  7. long long gd = a * b / __gcd(a * b, i);
  8. if ((b + 1 ) % gd == 0) {
  9. cout << i << " " << b + 1 << endl;
  10. return;
  11. }
  12. if (d % gd == 0) {
  13. cout << i << " " << d << endl;
  14. return;
  15. }
  16. if ((b + 1 ) / gd == d / gd) {
  17. continue;
  18. }
  19. cout << i << " " << d / gd *gd << endl;
  20. return;
  21. }
  22. cout << -1 << " " << -1 << endl;
  23. return;
  24. }
  25. int main() {
  26. int n;
  27. cin >> n;
  28. while (n--) {
  29. solve();
  30. }
  31. return 0;
  32. }

E2 - Divisible Numbers(hard version)

思路:相比E1,数据范围从1e5增大到1e9。关键要注意到,当我们遍历i时,有用的其实只是a*b/gcd(a*b,i),因此这其中进行了大量重复!我们自然想到,如果不遍历i,只遍历a*b/gcd(a*b,i),就能省去这些重复,而a*b/gcd(a*b,i)一定是a*b的因数!

因此本题先预处理分解质因数,再用dfs遍历所有因数。其余过程与E1相同。

时间复杂度呢?a*b的范围小于1e18,而1e18以内因数数量的最大值在11万左右(可百度查询)。因此不同担心超时问题。

代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. map<int, int> ys;
  4. int A[100100], B[100010];
  5. int cnt;
  6. long long a, b, c, d, ANSX, ANSY;
  7. long long fx(long long x) {
  8. return (a + 1 + x - 1) / x * x;
  9. }
  10. void q(int x) {
  11. for (int i = 2; i * i <= x; i++) {
  12. while (x % i == 0) {
  13. ys[i]++;
  14. x /= i;
  15. }
  16. }
  17. if (x > 1)
  18. ys[x]++;
  19. return;
  20. }//预处理因数
  21. long long sosolve(long long dq) {
  22. dq = fx(dq);
  23. if (dq <= a || dq > c)
  24. return -1;
  25. __int128 gd = a * b / __gcd(a * b, dq);
  26. if ((b + 1 ) % gd == 0) {
  27. return b + 1;
  28. }
  29. if (d % gd == 0) {
  30. return d;
  31. }
  32. if ((b + 1 ) / gd == d / gd) {
  33. return -1;
  34. }
  35. return d / gd * gd;
  36. }
  37. void dfs(long long dq, int step) {
  38. if (step > cnt - 1) {
  39. int y = sosolve(dq);
  40. if (y != -1) {
  41. ANSX = fx(dq);
  42. ANSY = y;
  43. }
  44. return;
  45. }
  46. __int128 k = 1;
  47. for (int i = 0; i <= B[step]; i++) {
  48. dfs(dq * k, step + 1);
  49. k *= A[step];
  50. }
  51. }
  52. void solve() {
  53. ys.clear();
  54. cin >> a >> b >> c >> d;
  55. q(a);
  56. q(b);
  57. map<int, int>::iterator t;
  58. cnt = 0;
  59. for (t = ys.begin(); t != ys.end(); t++) {
  60. A[cnt] = t->first;
  61. B[cnt] = t->second;
  62. cnt++;
  63. }
  64. ANSX = -1;
  65. ANSY = -1;
  66. dfs(1, 0);
  67. cout << ANSX << " " << ANSY << endl;
  68. return;
  69. }
  70. int main() {
  71. int n;
  72. cin >> n;
  73. while (n--) {
  74. solve();
  75. }
  76. return 0;
  77. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/72521
推荐阅读
相关标签
  

闽ICP备14008679号