[关闭]
@qq290637843 2021-01-23T04:40:27.000000Z 字数 25702 阅读 346

2019银川

题目见https://www.jisuanke.com/contest/5527/challenges,其中N题不知道题面在哪找。

A、Girls Band Party

按照是否有第一类加成和是否有第二类加成分为四类,每一类最多留下五个基价值最高的不同名字,然后总共最多二十张卡作为选择,最后暴力二十选五。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul T;
  7. using card = std::pair<std::string, std::string>;
  8. std::map<card, ul> map1;
  9. ul n;
  10. char str1[11], str2[11];
  11. std::string bonuscolor;
  12. using namep = std::pair<std::string, ul>;
  13. std::vector<namep> other[2];
  14. std::map<std::string, ul> nameid;
  15. ul power[16][2];
  16. std::set<std::string> already;
  17. ul tot = 0;
  18. using cd = std::pair<ul, ul>;
  19. cd sp[21];
  20. int main()
  21. {
  22. std::scanf("%u", &T);
  23. for (ul Case = 1; Case <= T; ++Case) {
  24. std::scanf("%u", &n);
  25. map1.clear();
  26. for (ul i = 1; i <= n; ++i) {
  27. ul p;
  28. std::scanf("%s%s%u", &str1, &str2, &p);
  29. auto& v = map1[card(std::string(str1), std::string(str2))];
  30. v = std::max(v, p);
  31. }
  32. nameid.clear();
  33. for (ul i = 1; i <= 5; ++i) {
  34. std::scanf("%s", &str1);
  35. nameid[str1] = i;
  36. }
  37. std::scanf("%s", &str1);
  38. bonuscolor = str1;
  39. other[0].resize(0);
  40. other[1].resize(0);
  41. std::memset(power, 0, sizeof(power));
  42. for (const auto& p : map1) {
  43. auto it = nameid.find(p.first.first);
  44. if (it != nameid.end()) {
  45. auto& v = power[it->second][p.first.second == bonuscolor];
  46. v = std::max(v, p.second);
  47. } else {
  48. other[p.first.second == bonuscolor].push_back(namep(p.first.first, p.second));
  49. }
  50. }
  51. std::sort(other[0].begin(), other[0].end(), [](const namep& a, const namep& b){return a.second > b.second;});
  52. std::sort(other[1].begin(), other[1].end(), [](const namep& a, const namep& b){return a.second > b.second;});
  53. for (ul i = 0; i <= 1; ++i) {
  54. already.clear();
  55. for (const auto& p : other[i]) {
  56. if (already.insert(p.first).second) {
  57. auto& currnameid = nameid[p.first];
  58. if (!currnameid) {
  59. currnameid = nameid.size();
  60. }
  61. power[currnameid][i] = p.second;
  62. if (already.size() == 5) {
  63. break;
  64. }
  65. }
  66. }
  67. }
  68. tot = 0;
  69. for (ul i = 1; i <= nameid.size(); ++i) {
  70. for (ul j = 0; j <= 1; ++j) {
  71. if (power[i][j]) {
  72. ++tot;
  73. sp[tot].first = i;
  74. sp[tot].second = j;
  75. }
  76. }
  77. }
  78. ul base = 0;
  79. ul ans = 0;
  80. ul bonus = 0;
  81. for (ul a = 1; a + 4 <= tot; ++a) {
  82. base += power[sp[a].first][sp[a].second];
  83. if (sp[a].first <= 5) {
  84. bonus += 1;
  85. }
  86. if (sp[a].second) {
  87. bonus += 2;
  88. }
  89. for (ul b = a + 1; b + 3 <= tot; ++b) {
  90. if (sp[a].first == sp[b].first) {
  91. continue;
  92. }
  93. base += power[sp[b].first][sp[b].second];
  94. if (sp[b].first <= 5) {
  95. bonus += 1;
  96. }
  97. if (sp[b].second) {
  98. bonus += 2;
  99. }
  100. for (ul c = b + 1; c + 2 <= tot; ++c) {
  101. if (sp[c].first == sp[b].first) {
  102. continue;
  103. }
  104. base += power[sp[c].first][sp[c].second];
  105. if (sp[c].first <= 5) {
  106. bonus += 1;
  107. }
  108. if (sp[c].second) {
  109. bonus += 2;
  110. }
  111. for (ul d = c + 1; d + 1 <= tot; ++d) {
  112. if (sp[d].first == sp[c].first) {
  113. continue;
  114. }
  115. base += power[sp[d].first][sp[d].second];
  116. if (sp[d].first <= 5) {
  117. bonus += 1;
  118. }
  119. if (sp[d].second) {
  120. bonus += 2;
  121. }
  122. for (ul e = d + 1; e <= tot; ++e) {
  123. if (sp[e].first == sp[d].first) {
  124. continue;
  125. }
  126. base += power[sp[e].first][sp[e].second];
  127. if (sp[e].first <= 5) {
  128. bonus += 1;
  129. }
  130. if (sp[e].second) {
  131. bonus += 2;
  132. }
  133. ans = std::max(ans, base * (10 + bonus) / 10);
  134. base -= power[sp[e].first][sp[e].second];
  135. if (sp[e].first <= 5) {
  136. bonus -= 1;
  137. }
  138. if (sp[e].second) {
  139. bonus -= 2;
  140. }
  141. }
  142. base -= power[sp[d].first][sp[d].second];
  143. if (sp[d].first <= 5) {
  144. bonus -= 1;
  145. }
  146. if (sp[d].second) {
  147. bonus -= 2;
  148. }
  149. }
  150. base -= power[sp[c].first][sp[c].second];
  151. if (sp[c].first <= 5) {
  152. bonus -= 1;
  153. }
  154. if (sp[c].second) {
  155. bonus -= 2;
  156. }
  157. }
  158. base -= power[sp[b].first][sp[b].second];
  159. if (sp[b].first <= 5) {
  160. bonus -= 1;
  161. }
  162. if (sp[b].second) {
  163. bonus -= 2;
  164. }
  165. }
  166. base -= power[sp[a].first][sp[a].second];
  167. if (sp[a].first <= 5) {
  168. bonus -= 1;
  169. }
  170. if (sp[a].second) {
  171. bonus -= 2;
  172. }
  173. }
  174. std::printf("%u\n", ans);
  175. }
  176. return 0;
  177. }

B、So Easy

简单题

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul n;
  7. const li maxn = 1000;
  8. li v[maxn][maxn];
  9. ul a, b;
  10. int main()
  11. {
  12. std::scanf("%u", &n);
  13. for (ul i = 0; i < n; ++i) {
  14. for (ul j = 0; j < n; ++j) {
  15. std::scanf("%d", &v[i][j]);
  16. if (v[i][j] < 0) {
  17. a = i;
  18. b = j;
  19. }
  20. }
  21. }
  22. std::printf("%d\n", v[(a + 1) % n][b] + v[a][(b + 1) % n] - v[(a + 1) % n][(b + 1) % n]);
  23. return 0;
  24. }

C、Image Processing

于是对于满足如下递推式:
由于如果,故如果,这说明在这种情况下,必定没有保留的价值,所以对于求,只需要保留的单调(升)栈。现在注意在单调栈内如果,那么由于于是,又因为,故,又因为,故,故,这就说明随着增大,最优一定可以是不降的,故上文中的单调栈改为单调队列即可。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul n, k;
  7. const ul maxn = 1e6;
  8. using pulul = std::pair<ul, ul>;
  9. std::deque<pulul> cqueue;
  10. std::deque<pulul> vqueueu;
  11. std::deque<pulul> vqueued;
  12. ul c[maxn + 1];
  13. ul g(ul x, bool re)
  14. {
  15. if (re) {
  16. ul l, r;
  17. l = -1;
  18. r = vqueueu.size() - 1;
  19. while (l + 1 != r) {
  20. ul mid = l + r >> 1;
  21. if (vqueueu[mid].first < x) {
  22. l = mid;
  23. } else {
  24. r = mid;
  25. }
  26. }
  27. ul u = vqueueu[r].second;
  28. l = -1;
  29. r = vqueued.size() - 1;
  30. while (l + 1 != r) {
  31. ul mid = l + r >> 1;
  32. if (vqueued[mid].first < x) {
  33. l = mid;
  34. } else {
  35. r = mid;
  36. }
  37. }
  38. ul d = vqueued[r].second;
  39. return d - u;
  40. } else {
  41. while (vqueueu.front().first < x) {
  42. vqueueu.pop_front();
  43. }
  44. while (vqueued.front().first < x) {
  45. vqueued.pop_front();
  46. }
  47. return vqueued.front().second - vqueueu.front().second;
  48. }
  49. }
  50. int main()
  51. {
  52. std::scanf("%u%u", &n, &k);
  53. for (ul i = 1; i <= n; ++i) {
  54. ul v;
  55. std::scanf("%u", &v);
  56. v ^= c[i - 1];
  57. while (vqueueu.size() && vqueueu.back().second >= v) {
  58. vqueueu.pop_back();
  59. }
  60. vqueueu.push_back(pulul(i, v));
  61. while (vqueued.size() && vqueued.back().second <= v) {
  62. vqueued.pop_back();
  63. }
  64. vqueued.push_back(pulul(i, v));
  65. if (i < k) {
  66. c[i] = 0;
  67. } else if (i < k + k) {
  68. c[i] = vqueued.front().second - vqueueu.front().second;
  69. } else {
  70. while (cqueue.size() && cqueue.back().second >= c[i - k]) {
  71. cqueue.pop_back();
  72. }
  73. cqueue.push_back(pulul(i - k, c[i - k]));
  74. while (cqueue.size() >= 2 && std::max(cqueue[0].second, g(cqueue[0].first + 1, false)) >= std::max(cqueue[1].second, g(cqueue[1].first + 1, true))) {
  75. cqueue.pop_front();
  76. }
  77. c[i] = std::max(cqueue[0].second, g(cqueue[0].first + 1, false));
  78. }
  79. }
  80. for (ul i = 1; i <= n; ++i) {
  81. std::printf("%u\n", c[i]);
  82. }
  83. return 0;
  84. }

D、Easy Problem

下文将简记为

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul mod = 59964251;
  7. const ul phi = 59870352;
  8. ul plus(ul a, ul b)
  9. {
  10. return a + b < mod ? a + b : a + b - mod;
  11. }
  12. ul minus(ul a, ul b)
  13. {
  14. return a < b ? a + mod - b : a - b;
  15. }
  16. ul mul(ul a, ul b)
  17. {
  18. return ull(a) * ull(b) % mod;
  19. }
  20. ul pow(ul a, ul b)
  21. {
  22. ul ret = 1;
  23. while (b) {
  24. if (b & 1) {
  25. ret = mul(ret, a);
  26. }
  27. a = mul(a, a);
  28. b >>= 1;
  29. }
  30. return ret;
  31. }
  32. ul T;
  33. ul m, d, k;
  34. char str[100002];
  35. ull n;
  36. const ul maxm = 1e5;
  37. ul sak[maxm + 1];
  38. ul ak[maxm + 1];
  39. std::vector<ul> prime;
  40. ul mu[maxm + 1];
  41. bool notprime[maxm + 1];
  42. int main()
  43. {
  44. mu[1] = 1;
  45. for (ul i = 2; i <= maxm; ++i) {
  46. if (!notprime[i]) {
  47. mu[i] = minus(0, 1);
  48. prime.push_back(i);
  49. }
  50. for (ul p : prime) {
  51. if (p * i > maxm) {
  52. break;
  53. }
  54. notprime[p * i] = true;
  55. if (i % p == 0) {
  56. mu[p * i] = 0;
  57. break;
  58. } else {
  59. mu[p * i] = minus(0, mu[i]);
  60. }
  61. }
  62. }
  63. std::scanf("%u", &T);
  64. for (ul Case = 1; Case <= T; ++Case) {
  65. std::scanf("%s", str + 1);
  66. n = 0;
  67. for (ul i = 1; str[i]; ++i) {
  68. n *= 10;
  69. n += str[i] - '0';
  70. if (n >= phi + phi) {
  71. n %= phi;
  72. n += phi;
  73. }
  74. }
  75. std::scanf("%u%u%u", &m, &d, &k);
  76. for (ul a = 1; a * d <= m; ++a) {
  77. ak[a] = pow(a, k);
  78. sak[a] = plus(sak[a - 1], ak[a]);
  79. }
  80. ul ans = 0;
  81. for (ul t = 1; t * d <= m; ++t) {
  82. if (mu[t]) {
  83. ans = plus(ans, mul(pow(mul(ak[t], sak[m / d / t]), n), mu[t]));
  84. }
  85. }
  86. ans = mul(ans, pow(pow(d, k), n));
  87. std::printf("%u\n", ans);
  88. }
  89. return 0;
  90. }

E、XOR Tree

下文中表示在二进制下位的数。
首先考虑两个数列,那么

其中
于是当两个数列相同的时候为
而原题意中不重复考虑,故为
至于的事,先直接求个下缀和,再从上向下每个点的阶祖先都减掉此位置就行。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul n, k;
  7. const ul maxn = 1e5;
  8. ul cnt[maxn + 1];
  9. ul A[maxn + 1][32][32];
  10. ul a;
  11. ul f[maxn + 1];
  12. std::vector<ul> sons[maxn + 1];
  13. std::vector<ul> stack;
  14. void search(ul curr)
  15. {
  16. ul depth = stack.size();
  17. stack.push_back(curr);
  18. if (depth >= k + 1) {
  19. cnt[stack[depth - k - 1]] -= cnt[curr];
  20. for (ul s = 0; s != 32; ++s) {
  21. for (ul t = 0; t != 32; ++t) {
  22. A[stack[depth - k - 1]][s][t] -= A[curr][s][t];
  23. }
  24. }
  25. }
  26. for (ul next : sons[curr]) {
  27. search(next);
  28. }
  29. stack.pop_back();
  30. }
  31. int main()
  32. {
  33. std::scanf("%u%u", &n, &k);
  34. for (ul i = 1; i <= n; ++i) {
  35. std::scanf("%u", &a);
  36. for (ul s = 0; s != 32; ++s) {
  37. if (a >> s & 1) {
  38. for (ul t = 0; t != 32; ++t) {
  39. if (a >> t & 1) {
  40. A[i][s][t] = 1;
  41. }
  42. }
  43. }
  44. }
  45. cnt[i] = 1;
  46. }
  47. for (ul i = 2; i <= n; ++i) {
  48. std::scanf("%u", &f[i]);
  49. sons[f[i]].push_back(i);
  50. }
  51. for (ul i = n; i >= 2; --i) {
  52. cnt[f[i]] += cnt[i];
  53. for (ul s = 0; s != 32; ++s) {
  54. for (ul t = 0; t != 32; ++t) {
  55. A[f[i]][s][t] += A[i][s][t];
  56. }
  57. }
  58. }
  59. search(1);
  60. for (ul i = 1; i <= n; ++i) {
  61. ull ans = 0;
  62. for (ul s = 0; s != 32; ++s) {
  63. for (ul t = 0; t != 32; ++t) {
  64. ans += ull(cnt[i]) * ull(A[i][s][t]) + ull(A[i][s][s]) * ull(A[i][t][t]) - 2 * ull(A[i][s][t]) * ull(A[i][t][t]) - 2 * ull(A[i][s][t]) * ull(A[i][s][s]) + 2 * ull(A[i][s][t]) * ull(A[i][s][t]) << s << t;
  65. }
  66. }
  67. std::printf("%llu\n", ans);
  68. }
  69. return 0;
  70. }

F、Function!

对于相等的区间分开处理即可。
注意最大只能取到,整数的次前缀和随便怎么预处理都可以。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul mod = 998244353;
  7. ul plus(ul a, ul b)
  8. {
  9. return a + b < mod ? a + b : a + b - mod;
  10. }
  11. ul minus(ul a, ul b)
  12. {
  13. return a < b ? a + mod - b : a - b;
  14. }
  15. ul mul(ul a, ul b)
  16. {
  17. return ull(a) * ull(b) % mod;
  18. }
  19. ul pow(ul a, ul b)
  20. {
  21. ul ret = 1;
  22. while (b) {
  23. if (b & 1) {
  24. ret = mul(ret, a);
  25. }
  26. a = mul(a, a);
  27. b >>= 1;
  28. }
  29. return ret;
  30. }
  31. void exgcd(li a, li b, li& x, li& y)
  32. {
  33. if (b) {
  34. exgcd(b, a % b, y, x);
  35. y -= a / b * x;
  36. } else {
  37. x = 1;
  38. y = 0;
  39. }
  40. }
  41. ul inverse(ul a)
  42. {
  43. li x, y;
  44. exgcd(a, mod, x, y);
  45. return x < 0 ? x + li(mod) : x;
  46. }
  47. ul bm(const ul s[], ul cc[], ul nn)
  48. {
  49. static ul bb[200];
  50. static ul tt[200];
  51. cc[0] = 1;
  52. bb[0] = 1;
  53. ul tl;
  54. ul bl = 0;
  55. ul l = 0;
  56. ul m = 1;
  57. ul b = 1;
  58. for (ul n = 0; n != nn; ++n) {
  59. ul d = 0;
  60. for (ul i = 0; i <= l; ++i) {
  61. d = plus(d, mul(cc[i], s[n - i]));
  62. }
  63. if (d == 0) {
  64. ++m;
  65. } else if (l + l <= n) {
  66. std::memcpy(tt, cc, sizeof(ul) * (l + 1));
  67. tl = l;
  68. std::memset(&cc[l + 1], 0, sizeof(ul) * (n - l - l + 1));
  69. l = n + 1 - l;
  70. ul lambda = mul(inverse(b), d);
  71. for (ul i = 0; i <= bl; ++i) {
  72. cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));
  73. }
  74. bl = tl;
  75. std::memcpy(bb, tt, sizeof(ul) * (bl + 1));
  76. b = d;
  77. m = 1;
  78. } else {
  79. ul lambda = mul(inverse(b), d);
  80. for (ul i = 0; i <= bl; ++i) {
  81. cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));
  82. }
  83. ++m;
  84. }
  85. }
  86. return l;
  87. }
  88. ul linearrec(const ul s[], const ul tcc[], ul len, ull n)
  89. {
  90. static ul cc[200];
  91. static ul ret[200];
  92. static ul temp[200];
  93. if (n < len) {
  94. return s[n];
  95. }
  96. std::memcpy(cc, tcc, sizeof(ul) * (len + 1));
  97. std::memset(ret, 0, sizeof(ul) * len);
  98. ret[0] = 1;
  99. ul dret = 0;
  100. for (ull t = ull(1) << 63 - __builtin_clzll(n); t; t >>= 1) {
  101. std::memset(temp, 0, sizeof(ul) * (dret + dret + 1));
  102. for (ul i = 0; i <= dret; ++i) {
  103. temp[i + i] = plus(temp[i + i], mul(ret[i], ret[i]));
  104. for (ul j = i + 1; j <= dret; ++j) {
  105. ul tp = mul(ret[i], ret[j]);
  106. temp[i + j] = plus(temp[i + j], plus(tp, tp));
  107. }
  108. }
  109. for (ul i = dret + dret; i >= len; --i) {
  110. ul lambda = minus(0, temp[i]);
  111. if (!lambda) {
  112. continue;
  113. }
  114. for (ul j = 0; j <= len; ++j) {
  115. temp[i - j] = plus(temp[i - j], mul(cc[j], lambda));
  116. }
  117. }
  118. std::memcpy(ret, temp, sizeof(ul) * len);
  119. dret = std::min(dret + dret, len - ul(1));
  120. if (t & n) {
  121. for (ul i = dret + 1; i; --i) {
  122. ret[i] = ret[i - 1];
  123. }
  124. ret[0] = 0;
  125. ++dret;
  126. if (dret == len) {
  127. ul lambda = minus(0, ret[len]);
  128. if (lambda) {
  129. for (ul i = 0; i <= len; ++i) {
  130. ret[len - i] = plus(ret[len - i], mul(cc[i], lambda));
  131. }
  132. }
  133. --dret;
  134. }
  135. }
  136. }
  137. ul out = 0;
  138. for (ul i = 0; i != len; ++i) {
  139. out = plus(out, mul(s[i], ret[i]));
  140. }
  141. return out;
  142. }
  143. const ul maxt = 40;
  144. ul s[maxt + 1][maxt + maxt + 4];
  145. ul cc[maxt + 1][maxt + 3];
  146. ul len[maxt + 1];
  147. ull n;
  148. using lf = double;
  149. ull powroot(ull a, ul b)
  150. {
  151. ull tmp = std::llround(std::pow(a, lf(1) / lf(b)));
  152. if (std::pow(tmp, b) > n) {
  153. --tmp;
  154. }
  155. return tmp;
  156. }
  157. const ul inv2 = mod + 1 >> 1;
  158. int main()
  159. {
  160. std::scanf("%llu", &n);
  161. for (ul t = 2; (ull(1) << t - 1) <= n; ++t) {
  162. for (ul x = 1; x <= t + t + 3; ++x) {
  163. s[t][x] = plus(s[t][x - 1], pow(x, t));
  164. }
  165. len[t] = bm(s[t], cc[t], t + t + 4);
  166. }
  167. ul ans = 0;
  168. for (ul k = 1; (ull(1) << k) <= n; ++k) {
  169. ull l = powroot(n, k + 1) + 1;
  170. ull r = powroot(n, k);
  171. ans = plus(ans, mul(k, mul((n + 1) % mod, mul((l + r) % mod, mul((r - l + 1) % mod, inv2)))));
  172. ans = minus(ans, minus(linearrec(s[k + 1], cc[k + 1], len[k + 1], r), 1));
  173. }
  174. std::printf("%u\n", ans);
  175. return 0;
  176. }

G、Pot!!

简单题

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul n, q;
  7. const ul sz = 1 << 17;
  8. li tree[11][sz << 1];
  9. void change(ul l, ul r, li val, li tree[])
  10. {
  11. li temp;
  12. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  13. if (~l & 1) {
  14. tree[l ^ 1] += val;
  15. }
  16. if (r & 1) {
  17. tree[r ^ 1] += val;
  18. }
  19. temp = std::max(tree[l], tree[l ^ 1]);
  20. tree[l] -= temp;
  21. tree[l ^ 1] -= temp;
  22. tree[l >> 1] += temp;
  23. temp = std::max(tree[r], tree[r ^ 1]);
  24. tree[r] -= temp;
  25. tree[r ^ 1] -= temp;
  26. tree[r >> 1] += temp;
  27. }
  28. for (ul i = l; i >> 1; i >>= 1) {
  29. temp = std::max(tree[i], tree[i ^ 1]);
  30. tree[i] -= temp;
  31. tree[i ^ 1] -= temp;
  32. tree[i >> 1] += temp;
  33. }
  34. }
  35. li& maxx(li& a, li b)
  36. {
  37. return a = std::max(a, b);
  38. }
  39. li query(ul l, ul r, const li tree[])
  40. {
  41. li lans = -1e7;
  42. li rans = -1e7;
  43. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  44. if (~l & 1) {
  45. maxx(lans, tree[l ^ 1]);
  46. }
  47. if (r & 1) {
  48. maxx(rans, tree[r ^ 1]);
  49. }
  50. lans += tree[l >> 1];
  51. rans += tree[r >> 1];
  52. }
  53. li ans = std::max(lans, rans);
  54. for (ul i = l; i >> 1; i >>= 1) {
  55. ans += tree[i >> 1];
  56. }
  57. return ans;
  58. }
  59. char str[20];
  60. int main()
  61. {
  62. std::scanf("%u%u", &n, &q);
  63. for (ul i = 1; i <= q; ++i) {
  64. std::scanf("%s", str);
  65. if (str[1] == 'U') {
  66. ul l, r, x;
  67. std::scanf("%u%u%u", &l, &r, &x);
  68. for (ul p : {2, 3, 5, 7}) {
  69. ul t = 0;
  70. while (x % p == 0) {
  71. x /= p;
  72. ++t;
  73. }
  74. change(l, r, t, tree[p]);
  75. }
  76. } else {
  77. ul l, r;
  78. std::scanf("%u%u", &l, &r);
  79. std::printf("ANSWER %d\n", std::max(std::max(query(l, r, tree[2]), query(l, r, tree[3])), std::max(query(l, r, tree[5]), query(l, r, tree[7]))));
  80. }
  81. }
  82. return 0;
  83. }

H、Delivery Route

强连通分量内直接狄克斯特拉,强连通分量外按照拓扑序处理。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. ul n, x, y, s;
  7. const ul maxn = 25000;
  8. ul rk[maxn + 1];
  9. ul fa[maxn + 1];
  10. ul getfather(ul x)
  11. {
  12. return fa[x] == x ? x : fa[x] = getfather(fa[x]);
  13. }
  14. void connect(ul a, ul b)
  15. {
  16. a = getfather(a);
  17. b = getfather(b);
  18. if (a == b) {
  19. return;
  20. }
  21. if (rk[a] > rk[b]) {
  22. fa[b] = a;
  23. } else if (rk[b] > rk[a]) {
  24. fa[a] = b;
  25. } else {
  26. fa[a] = b;
  27. ++rk[b];
  28. }
  29. }
  30. class edge_t {
  31. public:
  32. ul to = 0;
  33. li c = 0;
  34. edge_t()=default;
  35. edge_t(ul a, li b): to(a), c(b) {}
  36. };
  37. std::vector<edge_t> edges[maxn + 1];
  38. std::vector<ul> bigedges[maxn + 1];
  39. ul cnt[maxn + 1];
  40. std::vector<ul> order;
  41. std::deque<ul> queue;
  42. bool operator<(const edge_t& a, const edge_t& b)
  43. {
  44. return a.c > b.c;
  45. }
  46. std::priority_queue<edge_t> heap[maxn + 1];
  47. li dis[maxn + 1];
  48. const li inf = 250000001;
  49. int main()
  50. {
  51. std::scanf("%u%u%u%u", &n, &x, &y, &s);
  52. for (ul i = 1; i <= n; ++i) {
  53. dis[i] = inf;
  54. fa[i] = i;
  55. }
  56. for (ul i = 1; i <= x; ++i) {
  57. ul a, b, c;
  58. std::scanf("%u%u%u", &a, &b, &c);
  59. edges[a].push_back(edge_t(b, c));
  60. edges[b].push_back(edge_t(a, c));
  61. connect(a, b);
  62. }
  63. for (ul i = 1; i <= y; ++i) {
  64. ul a, b;
  65. li c;
  66. std::scanf("%u%u%d", &a, &b, &c);
  67. edges[a].push_back(edge_t(b, c));
  68. bigedges[getfather(a)].push_back(getfather(b));
  69. ++cnt[getfather(b)];
  70. }
  71. for (ul i = 1; i <= n; ++i) {
  72. if (getfather(i) != i) {
  73. continue;
  74. }
  75. if (cnt[i] == 0) {
  76. queue.push_back(i);
  77. }
  78. }
  79. while (queue.size()) {
  80. ul curr = queue.front();
  81. queue.pop_front();
  82. order.push_back(curr);
  83. for (ul next : bigedges[curr]) {
  84. --cnt[next];
  85. if (!cnt[next]) {
  86. queue.push_back(next);
  87. }
  88. }
  89. }
  90. dis[s] = 0;
  91. heap[getfather(s)].push(edge_t(s, 0));
  92. for (const auto t : order) {
  93. while (heap[t].size()) {
  94. auto curr = heap[t].top();
  95. heap[t].pop();
  96. if (dis[curr.to] != curr.c) {
  97. continue;
  98. }
  99. for (const auto& next : edges[curr.to]) {
  100. if (dis[next.to] > curr.c + next.c) {
  101. dis[next.to] = curr.c + next.c;
  102. heap[getfather(next.to)].push(edge_t(next.to, curr.c + next.c));
  103. }
  104. }
  105. }
  106. }
  107. for (ul i = 1; i <= n; ++i) {
  108. if (dis[i] == inf) {
  109. std::printf("NO PATH\n");
  110. } else {
  111. std::printf("%d\n", dis[i]);
  112. }
  113. }
  114. return 0;
  115. }

I、Base62

简单题

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. using vul = std::vector<ul>;
  7. ul x, y;
  8. vul operator*(const vul& a, const vul& b)
  9. {
  10. static vul ret;
  11. ret.resize(0);
  12. if (a.empty() || b.empty()) {
  13. return ret;
  14. }
  15. ret.resize(a.size() + b.size() - 1, 0);
  16. for (ul i = 0; i != a.size(); ++i) {
  17. if (a[i]) {
  18. for (ul j = 0; j != b.size(); ++j) {
  19. ret[i + j] += a[i] * b[j];
  20. }
  21. }
  22. }
  23. for (ul i = 0; i != ret.size(); ++i) {
  24. ul k = ret[i] / y;
  25. ret[i] %= y;
  26. if (k) {
  27. if (ret.size() == i + 1) {
  28. ret.push_back(0);
  29. }
  30. ret[i + 1] += k;
  31. }
  32. }
  33. return ret;
  34. }
  35. vul operator+(const vul& a, const vul& b)
  36. {
  37. static vul ret;
  38. ret.resize(std::max(a.size(), b.size()));
  39. for (ul i = 0; i != ret.size(); ++i) {
  40. ret[i] = (i < a.size() ? a[i] : ul(0)) + (i < b.size() ? b[i] : ul(0));
  41. }
  42. for (ul i = 0; i != ret.size(); ++i) {
  43. ul k = ret[i] / y;
  44. ret[i] %= y;
  45. if (k) {
  46. if (ret.size() == i + 1) {
  47. ret.push_back(0);
  48. }
  49. ret[i + 1] += k;
  50. }
  51. }
  52. return ret;
  53. }
  54. vul xv, currv, pv;
  55. ul ctv[256];
  56. ul vtc[62];
  57. char z[121];
  58. int main()
  59. {
  60. std::scanf("%u%u", &x, &y);
  61. while (x) {
  62. xv.push_back(x % y);
  63. x /= y;
  64. }
  65. for (ul i = 0; i <= 9; ++i) {
  66. ctv['0' + i] = i;
  67. vtc[i] = '0' + i;
  68. }
  69. for (ul i = 0; i <= 25; ++i) {
  70. ctv['A' + i] = 10 + i;
  71. vtc[10 + i] = 'A' + i;
  72. }
  73. for (ul i = 0; i <= 25; ++i) {
  74. ctv['a' + i] = 36 + i;
  75. vtc[36 + i] = 'a' + i;
  76. }
  77. std::scanf("%s", z);
  78. for (ul i = 0; z[i]; ++i) {
  79. ul p = ctv[z[i]];
  80. pv.resize(0);
  81. while (p) {
  82. pv.push_back(p % y);
  83. p /= y;
  84. }
  85. currv = currv * xv + pv;
  86. }
  87. if (currv.empty()) {
  88. std::printf("0\n");
  89. return 0;
  90. }
  91. for (ul i = currv.size() - 1; ~i; --i) {
  92. std::putchar(char(vtc[currv[i]]));
  93. }
  94. std::putchar('\n');
  95. return 0;
  96. }

J、Toad’s Travel

首先注意到,实际就是要求给每条边赋权,使得所有点的度数都是偶数,或者有两个奇度点,且其中一个是,那么显然所有边最少被走一次,最多被走两次。那么可以考虑动态规划。代码中ans_t的数组v[][],表示根当前度数奇偶性为,根之外有个奇度点的最小花费,而ans2_t中的数组v[][][]是给“有两个根的结构”准备的,其中分别表示两头的度数的奇偶性,表示两头之外有多少个奇度点。至于深搜过程,实际就是点双连通分量的写法,dfn[]表示的深搜序,low[]表示从出发走一些(可以是零条)树边最多再走一条回边能到达的深搜序最小的点的深搜序。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. const ul maxn = 1e5;
  7. ul n, m;
  8. class edge_t {
  9. public:
  10. ul to = 0;
  11. ul len = 0;
  12. edge_t()=default;
  13. edge_t(ul a, ul b): to(a), len(b) {}
  14. };
  15. std::vector<edge_t> edges[maxn + 1];
  16. ul dfn[maxn + 1];
  17. ul low[maxn + 1];
  18. const ull inf = 1e18;
  19. class ans_t {
  20. public:
  21. ull v[2][2];
  22. ans_t() {
  23. for (ul a : {0, 1}) {
  24. for (ul b : {0, 1}) {
  25. v[a][b] = inf;
  26. }
  27. }
  28. }
  29. ans_t(ul x) {
  30. for (ul a : {0, 1}) {
  31. for (ul b : {0, 1}) {
  32. v[a][b] = inf;
  33. }
  34. }
  35. v[0][0] = 0;
  36. }
  37. ull* operator[](ul x) {
  38. return v[x];
  39. }
  40. const ull* operator[](ul x) const {
  41. return v[x];
  42. }
  43. };
  44. class ans2_t {
  45. public:
  46. ull v[2][2][2];
  47. ans2_t() {
  48. for (ul a : {0, 1}) {
  49. for (ul b : {0, 1}) {
  50. for (ul c : {0, 1}) {
  51. v[a][b][c] = inf;
  52. }
  53. }
  54. }
  55. }
  56. using ttt = ull[2];
  57. ttt* operator[](ul x) {
  58. return v[x];
  59. }
  60. const ttt* operator[](ul x) const {
  61. return v[x];
  62. }
  63. };
  64. ans_t ans[maxn + 1];
  65. ans_t deal1(const ans_t& a, const ans_t& b, ul len)
  66. {
  67. ans_t ret;
  68. for (ul ar : {0, 1}) {
  69. for (ul al : {0, 1}) {
  70. if (a[ar][al] == inf) {
  71. continue;
  72. }
  73. for (ul br : {0, 1}) {
  74. for (ul bl : {0, 1}) {
  75. if (al && bl) {
  76. continue;
  77. }
  78. if (b[br][bl] == inf) {
  79. continue;
  80. }
  81. for (ul w : {1, 2}) {
  82. ul cr = (ar ^ w) & 1;
  83. ul cl = al + ((br ^ w) & 1) + bl;
  84. if (cl >= 2) {
  85. continue;
  86. }
  87. ret[cr][cl] = std::min(ret[cr][cl], a[ar][al] + b[br][bl] + w * len);
  88. }
  89. }
  90. }
  91. }
  92. }
  93. return ret;
  94. }
  95. ans2_t deal2(const ans_t& a, const ans_t& b, ul len)
  96. {
  97. ans2_t ret;
  98. for (ul ar : {0, 1}) {
  99. for (ul al : {0, 1}) {
  100. if (a[ar][al] == inf) {
  101. continue;
  102. }
  103. for (ul br : {0, 1}) {
  104. for (ul bl : {0, 1}) {
  105. if (al && bl) {
  106. continue;
  107. }
  108. if (b[br][bl] == inf) {
  109. continue;
  110. }
  111. for (ul w : {1, 2}) {
  112. ul cr1 = (ar ^ w) & 1;
  113. ul cr2 = (br ^ w) & 1;
  114. ul cl = al + bl;
  115. ret[cr1][cr2][cl] = std::min(ret[cr1][cr2][cl], a[ar][al] + b[br][bl] + w * len);
  116. }
  117. }
  118. }
  119. }
  120. }
  121. return ret;
  122. }
  123. ans2_t deal3(const ans_t& a, const ans2_t& b, ul len)
  124. {
  125. ans2_t ret;
  126. for (ul ar : {0, 1}) {
  127. for (ul al : {0, 1}) {
  128. if (a[ar][al] == inf) {
  129. continue;
  130. }
  131. for (ul br1 : {0, 1}) {
  132. for (ul br2 : {0, 1}) {
  133. for (ul bl : {0, 1}) {
  134. if (al && bl) {
  135. continue;
  136. }
  137. if (b[br1][br2][bl] == inf) {
  138. continue;
  139. }
  140. for (ul w : {1, 2}) {
  141. ul cr1 = (ar ^ w) & 1;
  142. ul cr2 = br2;
  143. ul cl = al + bl + ((br1 ^ w) & 1);
  144. if (cl >= 2) {
  145. continue;
  146. }
  147. ret[cr1][cr2][cl] = std::min(ret[cr1][cr2][cl], a[ar][al] + b[br1][br2][bl] + w * len);
  148. }
  149. }
  150. }
  151. }
  152. }
  153. }
  154. return ret;
  155. }
  156. ans_t deal4(const ans_t& a, const ans2_t& b, ul len)
  157. {
  158. ans_t ret;
  159. for (ul ar : {0, 1}) {
  160. for (ul al : {0, 1}) {
  161. if (a[ar][al] == inf) {
  162. continue;
  163. }
  164. for (ul br1 : {0, 1}) {
  165. for (ul br2 : {0, 1}) {
  166. for (ul bl : {0, 1}) {
  167. if (al && bl) {
  168. continue;
  169. }
  170. if (b[br1][br2][bl] == inf) {
  171. continue;
  172. }
  173. for (ul w : {1, 2}) {
  174. ul cr = (ar ^ w ^ br2) & 1;
  175. ul cl = al + bl + ((br1 ^ w) & 1);
  176. if (cl >= 2) {
  177. continue;
  178. }
  179. ret[cr][cl] = std::min(ret[cr][cl], a[ar][al] + b[br1][br2][bl] + w * len);
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }
  186. return ret;
  187. }
  188. ul tim;
  189. const ans_t zero(0);
  190. void search(ul v, ul u)
  191. {
  192. static std::vector<edge_t> stack;
  193. ++tim;
  194. dfn[v] = tim;
  195. low[v] = dfn[v];
  196. ans[v] = zero;
  197. for (const auto& e : edges[v]) {
  198. ul w = e.to;
  199. if (!dfn[w]) {
  200. stack.push_back(e);
  201. search(w, v);
  202. low[v] = std::min(low[v], low[w]);
  203. if (low[w] == dfn[v]) {
  204. auto laste = stack.back();
  205. stack.pop_back();
  206. ans2_t tmp = deal2(ans[stack.back().to], zero, laste.len);
  207. while (stack.back().to != w) {
  208. laste = stack.back();
  209. stack.pop_back();
  210. tmp = deal3(ans[stack.back().to], tmp, laste.len);
  211. }
  212. stack.pop_back();
  213. ans[v] = deal4(ans[v], tmp, e.len);
  214. } else if (low[w] > dfn[v]) {
  215. ans[v] = deal1(ans[v], ans[w], e.len);
  216. stack.pop_back();
  217. }
  218. } else if (dfn[w] < dfn[v] && w != u) {
  219. stack.push_back(e);
  220. low[v] = std::min(low[v], dfn[w]);
  221. }
  222. }
  223. }
  224. int main()
  225. {
  226. std::scanf("%u%u", &n, &m);
  227. for (ul i = 1; i <= m; ++i) {
  228. ul u, v, w;
  229. std::scanf("%u%u%u", &u, &v, &w);
  230. edges[u].push_back(edge_t(v, w));
  231. edges[v].push_back(edge_t(u, w));
  232. }
  233. search(1, 0);
  234. std::printf("%llu\n", std::min(ans[1][0][0], ans[1][1][1]));
  235. return 0;
  236. }

K、Largest Common Submatrix

由于题意说了任何数在一个数组中都只出现一次,所以此题实际和求零一数组的最大全零子数组是一样的做法。

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. using pulul = std::pair<ul, ul>;
  7. ul n, m;
  8. const ul maxn = 1000;
  9. const ul maxm = 1000;
  10. ul a[maxn + 1][maxm + 2];
  11. ul b[maxn + 1][maxm + 2];
  12. pulul pos[maxn * maxm + 1];
  13. ul h[maxn + 1][maxm + 1];
  14. ul l[maxn + 1][maxm + 1];
  15. std::vector<pulul> stack;
  16. int main()
  17. {
  18. std::scanf("%u%u", &n, &m);
  19. for (ul i = 1; i <= n; ++i) {
  20. for (ul j = 1; j <= m; ++j) {
  21. std::scanf("%u", &a[i][j]);
  22. pos[a[i][j]] = pulul(i, j);
  23. }
  24. }
  25. ul ans = 0;
  26. for (ul i = 1; i <= n; ++i) {
  27. stack.resize(0);
  28. stack.push_back(pulul(0, 0));
  29. for (ul j = 1; j <= m; ++j) {
  30. std::scanf("%u", &b[i][j]);
  31. if (a[pos[b[i][j]].first - 1][pos[b[i][j]].second] == b[i - 1][j]) {
  32. h[i][j] = h[i - 1][j] + 1;
  33. } else {
  34. h[i][j] = 1;
  35. }
  36. if (a[pos[b[i][j]].first][pos[b[i][j]].second - 1] != b[i][j - 1]) {
  37. stack.resize(0);
  38. stack.push_back(pulul(j - 1, 0));
  39. }
  40. while (stack.back().second >= h[i][j]) {
  41. stack.pop_back();
  42. }
  43. l[i][j] = stack.back().first + 1;
  44. stack.push_back(pulul(j, h[i][j]));
  45. }
  46. stack.resize(0);
  47. stack.push_back(pulul(m + 1, 0));
  48. for (ul j = m; j >= 1; --j) {
  49. if (a[pos[b[i][j]].first][pos[b[i][j]].second + 1] != b[i][j + 1]) {
  50. stack.resize(0);
  51. stack.push_back(pulul(j + 1, 0));
  52. }
  53. while (stack.back().second >= h[i][j]) {
  54. stack.pop_back();
  55. }
  56. ul r = stack.back().first - 1;
  57. ans = std::max((r - l[i][j] + 1) * h[i][j], ans);
  58. stack.push_back(pulul(j, h[i][j]));
  59. }
  60. }
  61. std::printf("%u\n", ans);
  62. return 0;
  63. }

L、Xian Xiang

预处理之后记忆化搜索

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. using pulul = std::pair<ul, ul>;
  7. ul T;
  8. ul n, m, k;
  9. const ul maxn = 7;
  10. const ul maxm = 7;
  11. const ul maxk = 5;
  12. char str[maxn + 1][maxm + 1][maxk + 1];
  13. ul tot;
  14. const ul maxtot = 18;
  15. pulul pos[maxtot + 1];
  16. ul s[maxk + 1];
  17. ul val[maxtot][maxtot + 1];
  18. ul ban[maxtot][maxtot + 1][2];
  19. ul ans[1 << maxtot];
  20. ul already[1 << maxtot];
  21. ul tim = 0;
  22. void search(ul curr)
  23. {
  24. if (already[curr] == tim) {
  25. return;
  26. }
  27. already[curr] = tim;
  28. ans[curr] = 0;
  29. for (ul mi = curr; __builtin_popcount(mi) >= 2; mi &= ~(1 << __builtin_ctz(mi))) {
  30. ul i = __builtin_ctz(mi) + 1;
  31. for (ul mj = mi & ~(1 << i - 1); mj; mj &= ~(1 << __builtin_ctz(mj))) {
  32. ul j = __builtin_ctz(mj) + 1;
  33. if ((curr & ban[i][j][0]) && (curr & ban[i][j][1])) {
  34. continue;
  35. }
  36. ul next = curr & ~(1 << i - 1) & ~(1 << j - 1);
  37. search(next);
  38. ans[curr] = std::max(ans[curr], ans[next] + val[i][j]);
  39. }
  40. }
  41. }
  42. int main()
  43. {
  44. std::scanf("%u", &T);
  45. for (ul Case = 1; Case <= T; ++Case) {
  46. std::scanf("%u%u%u", &n, &m, &k);
  47. tot = 0;
  48. for (ul i = 1; i <= n; ++i) {
  49. for (ul j = 1; j <= m; ++j) {
  50. std::scanf("%s", str[i][j]);
  51. if (str[i][j][0] != '-') {
  52. ++tot;
  53. pos[tot] = pulul(i, j);
  54. }
  55. }
  56. }
  57. for (ul i = 0; i <= k; ++i) {
  58. std::scanf("%u", &s[i]);
  59. }
  60. for (ul i = 1; i + 1 <= tot; ++i) {
  61. for (ul j = i + 1; j <= tot; ++j) {
  62. ul cnt = 0;
  63. for (ul q = 0; q != k; ++q) {
  64. if (str[pos[i].first][pos[i].second][q] == str[pos[j].first][pos[j].second][q]) {
  65. ++cnt;
  66. }
  67. }
  68. val[i][j] = s[cnt];
  69. ban[i][j][0] = ban[i][j][1] = 0;
  70. for (ul q = 1; q <= tot; ++q) {
  71. if (q == i || q == j) {
  72. continue;
  73. }
  74. if (pos[q].first == pos[i].first && (pos[q].second >= pos[i].second) == (pos[q].second <= pos[j].second)) {
  75. ban[i][j][0] |= 1 << q - 1;
  76. }
  77. if (pos[q].second == pos[j].second && (pos[q].first >= pos[i].first) == (pos[q].first <= pos[j].first)) {
  78. ban[i][j][0] |= 1 << q - 1;
  79. }
  80. if (pos[q].first == pos[j].first && (pos[q].second >= pos[i].second) == (pos[q].second <= pos[j].second)) {
  81. ban[i][j][1] |= 1 << q - 1;
  82. }
  83. if (pos[q].second == pos[i].second && (pos[q].first >= pos[i].first) == (pos[q].first <= pos[j].first)) {
  84. ban[i][j][1] |= 1 << q - 1;
  85. }
  86. }
  87. }
  88. }
  89. ++tim;
  90. already[0] = tim;
  91. ans[0] = 0;
  92. search((1 << tot) - 1);
  93. std::printf("%u\n", ans[(1 << tot) - 1]);
  94. }
  95. return 0;
  96. }

M、Crazy Cake

个点的,不考虑旋转一致性的问题的答案为。现在考虑用伯恩赛德引理,考虑将点转不变的方案数怎么求。首先这里定为的因数,如果不是,那么直接取为和的最大公因数即可。
注意,只要,那么不变的方案数就等于不变的方案数(这一点自己证明),记为。于是,输入为时的答案就应该是:

现在考虑怎么求。
显然有如下的递推式(自己证):
该式可改写为
关于
该式可改写为
现在定义,于是
解之得

,那么,于是

接着处理
,那么,于是

  1. #include <bits/stdc++.h>
  2. using ul = std::uint32_t;
  3. using li = std::int32_t;
  4. using ull = std::uint64_t;
  5. using ll = std::int64_t;
  6. using pulul = std::pair<ul, ul>;
  7. const ul mod = 1e9 + 7;
  8. const ul maxn = 1e6;
  9. ul plus(ul a, ul b)
  10. {
  11. return a + b < mod ? a + b : a + b - mod;
  12. }
  13. ul minus(ul a, ul b)
  14. {
  15. return a < b ? a + mod - b : a - b;
  16. }
  17. ul mul(ul a, ul b)
  18. {
  19. return ull(a) * ull(b) % mod;
  20. }
  21. void exgcd(li a, li b, li& x, li& y)
  22. {
  23. if (b) {
  24. exgcd(b, a % b, y, x);
  25. y -= a / b * x;
  26. } else {
  27. x = 1;
  28. y = 0;
  29. }
  30. }
  31. ul inverse(ul a)
  32. {
  33. li x, y;
  34. exgcd(a, mod, x, y);
  35. return x < 0 ? x + li(mod) : x;
  36. }
  37. ul h[maxn + 1];
  38. ul fac[maxn + 1];
  39. ul fiv[maxn + 1];
  40. ul inv[maxn + 1];
  41. ul f[maxn + 1];
  42. ul g[maxn + 1];
  43. ul low[maxn + 1];
  44. std::vector<ul> prime;
  45. ul phi[maxn + 1];
  46. ul T;
  47. std::vector<pulul> stack;
  48. ul ans;
  49. ul cnt[30];
  50. ul n;
  51. void search(ul i, ul k)
  52. {
  53. if (i == stack.size()) {
  54. if (k != 1) {
  55. ans = plus(ans, mul(phi[k], g[n / k]));
  56. }
  57. return;
  58. }
  59. for (cnt[i] = 0; cnt[i] <= stack[i].second; ++cnt[i], k *= stack[i].first) {
  60. search(i + 1, k);
  61. }
  62. }
  63. int main()
  64. {
  65. fac[0] = 1;
  66. for (ul i = 1; i <= maxn; ++i) {
  67. fac[i] = mul(fac[i - 1], i);
  68. }
  69. fiv[maxn] = inverse(fac[maxn]);
  70. for (ul i = maxn; i >= 1; --i) {
  71. fiv[i - 1] = mul(fiv[i], i);
  72. inv[i] = mul(fiv[i], fac[i - 1]);
  73. }
  74. h[0] = 1;
  75. h[1] = minus(0, 6);
  76. h[2] = minus(0, 16);
  77. for (ul n = 2; n + 1 <= maxn; ++n) {
  78. h[n + 1] = mul(inv[2], mul(inv[n + 1], minus(mul(24 * n - 12, h[n]), mul(8 * n - 16, h[n - 1]))));
  79. }
  80. f[1] = mul(3, inv[2]);
  81. f[2] = minus(0, 1);
  82. for (ul n = 0; n + 1 <= maxn; ++n) {
  83. f[n + 1] = minus(f[n + 1], mul(h[n], inv[2]));
  84. }
  85. h[0] = 1;
  86. h[1] = 6;
  87. h[2] = 52;
  88. for (ul n = 2; n + 1 <= maxn; ++n) {
  89. h[n + 1] = mul(inv[2], mul(inv[n + 1], minus(mul(24 * n + 12, h[n]), mul(8 * n, h[n - 1]))));
  90. }
  91. for (ul n = 0; n + 1 <= maxn; ++n) {
  92. g[n + 1] = plus(h[n], h[n]);
  93. }
  94. for (ul i = 2; i <= maxn; ++i) {
  95. if (!low[i]) {
  96. low[i] = i;
  97. prime.push_back(i);
  98. phi[i] = i - 1;
  99. }
  100. for (ul p : prime) {
  101. if (i * p > maxn) {
  102. break;
  103. }
  104. low[i * p] = p;
  105. if (i % p == 0) {
  106. phi[i * p] = phi[i] * p;
  107. break;
  108. } else {
  109. phi[i * p] = phi[i] * (p - 1);
  110. }
  111. }
  112. }
  113. std::scanf("%u", &T);
  114. for (ul Case = 1; Case <= T; ++Case) {
  115. std::scanf("%u", &n);
  116. ans = f[n];
  117. stack.resize(0);
  118. ul tn = n;
  119. while (tn != 1) {
  120. if (stack.empty() || stack.back().first != low[tn]) {
  121. stack.push_back(pulul(low[tn], 0));
  122. }
  123. ++stack.back().second;
  124. tn /= low[tn];
  125. }
  126. search(0, 1);
  127. std::printf("%u\n", mul(ans, inv[n]));
  128. }
  129. return 0;
  130. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注