[关闭]
@qq290637843 2020-12-01T22:33:49.000000Z 字数 29281 阅读 400

2020杭电第五场

A、Tetrahedron 6814

简单题

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. const ul base = 998244353;
  10. ul plus(ul a, ul b)
  11. {
  12. return a + b < base ? a + b : a + b - base;
  13. }
  14. ul mul(ul a, ul b)
  15. {
  16. return ull(a) * ull(b) % base;
  17. }
  18. const ul maxn = 6e6;
  19. ul T;
  20. ul n;
  21. ul inv[maxn + 1];
  22. ul sum[maxn + 1];
  23. int main()
  24. {
  25. std::ios::sync_with_stdio(false);
  26. std::cin.tie(0);
  27. iss.tie(0);
  28. oss.tie(0);
  29. std::getline(std::cin, instr, char(0));
  30. iss.str(instr);
  31. inv[1] = 1;
  32. sum[1] = 1;
  33. for (ul i = 2; i <= maxn; ++i) {
  34. inv[i] = ull(base - base / i) * inv[base % i] % base;
  35. sum[i] = plus(sum[i - 1], mul(inv[i], inv[i]));
  36. }
  37. iss >> T;
  38. for (ul Case = 1; Case <= T; ++Case) {
  39. iss >> n;
  40. oss << mul(mul(sum[n], 3), inv[n]) << '\n';
  41. }
  42. std::cout << oss.str();
  43. return 0;
  44. }

B、Funny String 6815

如果这个题没有像这样卡空间,其实直接后缀树就行了。
官方题解如下:
image.png-334.7kB
image.png-344kB
image.png-241.3kB

  1. #pragma GCC target ("pclmul")
  2. #include <bits/stdc++.h>
  3. #include <emmintrin.h>
  4. #include <wmmintrin.h>
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. using pulul = std::pair<ul, ul>;
  10. ul T;
  11. ul n, m, q;
  12. const ul maxn = 1e6;
  13. ul s[maxn + 1];
  14. ul tim;
  15. ul rk[maxn + 2];
  16. ul sa[maxn + 2];
  17. ul fa[maxn + 1];
  18. std::vector<ul> son[maxn + 2];
  19. std::vector<pulul> cnt[maxn + 2];
  20. class node {
  21. public:
  22. ul left = 0;
  23. ul right = 0;
  24. ul val = 0;
  25. node()=default;
  26. };
  27. std::vector<node> segtree(maxn * 21);
  28. ul currroot;
  29. void change(ul pos, ul val, ul l, ul r, ul& nid)
  30. {
  31. auto tmpnode = segtree[nid];
  32. tmpnode.val += val;
  33. if (l != r) {
  34. ul midl = l + r >> 1;
  35. ul midr = midl + 1;
  36. if (pos <= midl) {
  37. change(pos, val, l, midl, tmpnode.left);
  38. } else {
  39. change(pos, val, midr, r, tmpnode.right);
  40. }
  41. }
  42. segtree.push_back(tmpnode);
  43. nid = segtree.size() - 1;
  44. }
  45. ul query(ul l, ul r, ul nl, ul nr, ul nid)
  46. {
  47. if (nl >= l && nr <= r) {
  48. return segtree[nid].val;
  49. }
  50. ul ret = 0;
  51. ul midl = nl + nr >> 1;
  52. ul midr = midl + 1;
  53. if (l <= midl && segtree[nid].left) {
  54. ret += query(l, r, nl, midl, segtree[nid].left);
  55. }
  56. if (r >= midr && segtree[nid].right) {
  57. ret += query(l, r, midr, nr, segtree[nid].right);
  58. }
  59. return ret;
  60. }
  61. ul head[maxn + 2];
  62. void search(ul curr)
  63. {
  64. cnt[curr].resize(0);
  65. ++tim;
  66. ul prevroot = currroot;
  67. if (curr != n + 1) {
  68. change(s[curr + n + 1 - fa[curr]], 1, 1, m, currroot);
  69. }
  70. head[curr] = currroot;
  71. ul atim = tim;
  72. std::sort(son[curr].begin(), son[curr].end(), [&](ul a, ul b){return s[a + n + 1 - curr] < s[b + n + 1 - curr];});
  73. for (ul next : son[curr]) {
  74. search(next);
  75. if (cnt[curr].empty() || cnt[curr].back().first != s[next + n + 1 - curr]) {
  76. cnt[curr].push_back(pulul(s[next + n + 1 - curr], 0));
  77. }
  78. cnt[curr].back().second = tim - atim;
  79. }
  80. if (curr != n + 1) {
  81. currroot = prevroot;
  82. }
  83. }
  84. ul t, c, i;
  85. ul s2[maxn + 1], t1[maxn + 1], t2[maxn + 1], cc[maxn + 1];
  86. int main()
  87. {
  88. std::scanf("%u", &T);
  89. ul last = 0;
  90. for (ul Case = 1; Case <= T; ++Case) {
  91. std::scanf("%u%u%u", &n, &m, &q);
  92. for (ul i = 1; i <= n; ++i) {
  93. std::scanf("%u", &s[i]);
  94. son[i].resize(0);
  95. }
  96. son[n + 1].resize(0);
  97. for (ul i = 1; i <= n; ++i) {
  98. s2[i] = s[i];
  99. }
  100. std::sort(s2 + 1, s2 + n + 1);
  101. ul newm = std::unique(s2 + 1, s2 + n + 1) - s2 - 1;
  102. for (ul i = 1; i <= newm; ++i) {
  103. t1[s2[i]] = i;
  104. }
  105. for (ul i = 1; i <= n; ++i) {
  106. s2[i] = t1[s[i]];
  107. }
  108. ul *x = t1, *y = t2;
  109. std::memset(cc + 1, 0, newm * sizeof(ul));
  110. for (ul i = 1; i <= n; ++i) {
  111. ++cc[x[i] = s2[i]];
  112. }
  113. for (ul i = 1; i <= newm; ++i) {
  114. cc[i] += cc[i - 1];
  115. }
  116. for (ul i = n; i >= 1; --i) {
  117. sa[cc[x[i]]] = i;
  118. --cc[x[i]];
  119. }
  120. for (ul k = 1; k <= n; k <<= 1) {
  121. ul p = 1;
  122. for (ul i = n - k + 1; i <= n; ++i) {
  123. y[p] = i;
  124. ++p;
  125. }
  126. for (ul i = 1; i <= n; ++i) {
  127. if (sa[i] > k) {
  128. y[p] = sa[i] - k;
  129. ++p;
  130. }
  131. }
  132. std::memset(cc + 1, 0, newm * sizeof(ul));
  133. for (ul i = 1; i <= n; ++i) {
  134. ++cc[x[y[i]]];
  135. }
  136. for (ul i = 1; i <= newm; ++i) {
  137. cc[i] += cc[i - 1];
  138. }
  139. for (ul i = n; i >= 1; --i) {
  140. sa[cc[x[y[i]]]] = y[i];
  141. --cc[x[y[i]]];
  142. }
  143. std::swap(x, y);
  144. p = 2;
  145. x[sa[1]] = 1;
  146. for (ul i = 2; i <= n; ++i) {
  147. x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
  148. }
  149. if (p >= n) break;
  150. newm = p;
  151. }
  152. for (ul i = 1; i <= n; ++i) {
  153. rk[sa[i]] = i;
  154. }
  155. rk[n + 1] = 0;
  156. sa[0] = n + 1;
  157. fa[n] = n + 1;
  158. son[n + 1].push_back(n);
  159. for (ul i = n - 1; i >= 1; --i) {
  160. ul t;
  161. for (t = fa[i + 1]; t != n + 1 && s[t - 1] != s[i]; t = fa[t]);
  162. fa[i] = s[t - 1] == s[i] ? t - 1 : t;
  163. son[fa[i]].push_back(i);
  164. }
  165. tim = 0;
  166. segtree.resize(0);
  167. segtree.resize(1);
  168. currroot = 0;
  169. search(n + 1);
  170. last = 0;
  171. for (ul qid = 1; qid <= q; ++qid) {
  172. std::scanf("%u%u%u", &t, &c, &i);
  173. c ^= last;
  174. i ^= last;
  175. if (t == 1) {
  176. --i;
  177. if (i) {
  178. bool less;
  179. if (c != s[i]) {
  180. less = c < s[i];
  181. } else {
  182. less = rk[1] < rk[i + 1];
  183. }
  184. if (less) {
  185. last = rk[i] + 1;
  186. } else {
  187. last = rk[i];
  188. }
  189. } else {
  190. ul l = 0, r = n + 1;
  191. while (l + 1 != r) {
  192. ul mid = l + r >> 1;
  193. i = sa[mid];
  194. bool less;
  195. if (c != s[i]) {
  196. less = c < s[i];
  197. } else {
  198. less = rk[1] < rk[i + 1];
  199. }
  200. (less ? r : l) = mid;
  201. }
  202. last = r;
  203. }
  204. } else {
  205. ul tmp = rk[i] + 1;
  206. tmp -= query(1, c - 1, 1, m, head[i]);
  207. auto it = std::lower_bound(cnt[i].begin(), cnt[i].end(), pulul(c, 0));
  208. if (it != cnt[i].begin()) {
  209. tmp += std::prev(it)->second;
  210. }
  211. last = tmp;
  212. }
  213. std::printf("%u\n", last);
  214. }
  215. for (ul i = 1; i <= n + 1; ++i) {
  216. son[i].clear();
  217. cnt[i].clear();
  218. }
  219. }
  220. return 0;
  221. }

C、Boring Game 6816

简单题

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. ul T, n, k;
  10. const ul maxk = 10;
  11. std::vector<ul> stack[(1 << maxk) + 1];
  12. std::vector<ul> out;
  13. int main()
  14. {
  15. std::ios::sync_with_stdio(false);
  16. std::cin.tie(0);
  17. iss.tie(0);
  18. oss.tie(0);
  19. std::getline(std::cin, instr, char(0));
  20. iss.str(instr);
  21. iss >> T;
  22. for (ul Case = 1; Case <= T; ++Case) {
  23. iss >> n >> k;
  24. stack[1 << k].resize(0);
  25. for (ul i = 1; i <= (n << k + 1); ++i) {
  26. ul tmp;
  27. iss >> tmp;
  28. stack[1 << k].push_back(tmp);
  29. }
  30. std::reverse(stack[1 << k].begin(), stack[1 << k].end());
  31. for (ul a = 1; a <= k; ++a) {
  32. for (ul s = 1 << k, t = (1 << k) - (1 << a) + 1; s > t; --s, ++t) {
  33. stack[t].resize(0);
  34. while (stack[s].size() > stack[t].size()) {
  35. stack[t].push_back(stack[s].back());
  36. stack[s].pop_back();
  37. }
  38. }
  39. }
  40. out.resize(0);
  41. while (stack[1].size()) {
  42. for (ul i = 1; i <= (1 << k); ++i) {
  43. out.push_back(stack[i].back());
  44. stack[i].pop_back();
  45. }
  46. }
  47. for (ul i = 0; i != out.size(); ++i) {
  48. if (i) {
  49. oss << ' ';
  50. }
  51. oss << out[i];
  52. }
  53. oss << '\n';
  54. }
  55. std::cout << oss.str();
  56. return 0;
  57. }

D、Expression 6817

实际问题一并不需要,只需要,注意到


关于问题二,自己证明下方算法的正确性吧。注意每个变量只出现一次,这意味着每个变量的次数为一。

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. const ul mod = 998244353;
  10. ul plus(ul a, ul b)
  11. {
  12. return a + b < mod ? a + b : a + b - mod;
  13. }
  14. ul minus(ul a, ul b)
  15. {
  16. return a < b ? a + mod - b : a - b;
  17. }
  18. ul mul(ul a, ul b)
  19. {
  20. return ull(a) * ull(b) % mod;
  21. }
  22. void exgcd(li a, li b, li& x, li& y)
  23. {
  24. if (b) {
  25. exgcd(b, a % b, y, x);
  26. y -= a / b * x;
  27. } else {
  28. x = 1;
  29. y = 0;
  30. }
  31. }
  32. ul inverse(ul a)
  33. {
  34. li x, y;
  35. exgcd(a, mod, x, y);
  36. return x < 0 ? x + li(mod) : x;
  37. }
  38. ul T;
  39. const ul maxn = 1e4;
  40. ul n, L;
  41. class node {
  42. public:
  43. char op = 0;
  44. ul left = 0;
  45. ul right = 0;
  46. node()=default;
  47. node(char op, ul left, ul right): op(op), left(left), right(right) {}
  48. };
  49. std::vector<node> tree(maxn + maxn);
  50. std::vector<char> charstack;
  51. std::vector<ul> valstack;
  52. ul build(ul left, char op, ul right)
  53. {
  54. tree.push_back(node(op, left, right));
  55. return tree.size() - 1;
  56. }
  57. void onceout()
  58. {
  59. ul right = valstack.back();
  60. valstack.pop_back();
  61. ul left = valstack.back();
  62. valstack.pop_back();
  63. char op = charstack.back();
  64. charstack.pop_back();
  65. valstack.push_back(build(left, op, right));
  66. }
  67. ul ans[6][maxn + maxn];
  68. ul al[6][maxn + maxn];
  69. ul altim;
  70. ul head;
  71. ul bi[6][6];
  72. ul calc(ul t, ul id)
  73. {
  74. if (al[t][id] == altim) {
  75. return ans[t][id];
  76. }
  77. al[t][id] = altim;
  78. if (tree[id].op == '+') {
  79. return ans[t][id] = plus(calc(t, tree[id].left), calc(t, tree[id].right));
  80. } else if (tree[id].op == '-') {
  81. return ans[t][id] = minus(calc(t, tree[id].left), calc(t, tree[id].right));
  82. } else {
  83. ans[t][id] = 0;
  84. for (ul i = 0; i <= t; ++i) {
  85. ans[t][id] = plus(ans[t][id], mul(mul(bi[t][i], calc(i, tree[id].left)), calc(t - i, tree[id].right)));
  86. }
  87. return ans[t][id];
  88. }
  89. }
  90. class num {
  91. public:
  92. ul v = 1;
  93. ul cnt0 = 0;
  94. num(ul x = 1): v(x ? x : ul(1)), cnt0(!x) {}
  95. num(ul x, ul y): v(x), cnt0(y) {}
  96. };
  97. num operator*(const num& a, const num& b)
  98. {
  99. return num(mul(a.v, b.v), a.cnt0 + b.cnt0);
  100. }
  101. num f[maxn + maxn];
  102. num g[maxn + maxn];
  103. ul dfn[maxn + maxn];
  104. ul stleft[maxn + maxn][16];
  105. ul stright[maxn + maxn][16];
  106. ul tim = 0;
  107. void search(ul curr)
  108. {
  109. if (tree[curr].left) {
  110. if (tree[curr].op == '+' || tree[curr].op == '-') {
  111. f[tree[curr].left] = 1;
  112. } else {
  113. f[tree[curr].left] = calc(0, tree[curr].right);
  114. }
  115. g[tree[curr].left] = g[curr] * f[tree[curr].left];
  116. search(tree[curr].left);
  117. }
  118. ++tim;
  119. dfn[curr] = tim;
  120. stleft[tim][0] = curr;
  121. stright[tim][0] = curr;
  122. if (tree[curr].right) {
  123. if (tree[curr].op == '+') {
  124. f[tree[curr].right] = 1;
  125. } else if (tree[curr].op == '-') {
  126. f[tree[curr].right] = mod - 1;
  127. } else {
  128. f[tree[curr].right] = calc(0, tree[curr].left);
  129. }
  130. g[tree[curr].right] = g[curr] * f[tree[curr].right];
  131. search(tree[curr].right);
  132. }
  133. }
  134. ul lca(ul a, ul b)
  135. {
  136. a = dfn[a];
  137. b = dfn[b];
  138. if (a > b) {
  139. std::swap(a, b);
  140. }
  141. return std::max(stright[a][31 - __builtin_clz(b - a + 1)], stleft[b][31 - __builtin_clz(b - a + 1)]);
  142. }
  143. const ul maxt = 30;
  144. ul is[maxt + 1];
  145. int main()
  146. {
  147. std::ios::sync_with_stdio(false);
  148. std::cin.tie(0);
  149. iss.tie(0);
  150. oss.tie(0);
  151. std::getline(std::cin, instr, char(0));
  152. iss.str(instr);
  153. for (ul i = 0; i <= 5; ++i) {
  154. bi[i][0] = 1;
  155. for (ul j = 1; j <= i; ++j) {
  156. bi[i][j] = plus(bi[i - 1][j - 1], bi[i - 1][j]);
  157. }
  158. }
  159. iss >> T;
  160. for (ul Case = 1; Case <= T; ++Case) {
  161. iss >> L >> n;
  162. iss >> instr;
  163. charstack.resize(0);
  164. valstack.resize(0);
  165. tree.resize(0);
  166. tree.resize(n + 1);
  167. for (auto ch : instr) {
  168. if (ch == '[') {
  169. valstack.push_back(0);
  170. } else if (ch <= '9' && ch >= '0') {
  171. valstack.back() *= 10;
  172. valstack.back() += ch - '0';
  173. } else if (ch == ']') {
  174. } else if (ch == '(') {
  175. charstack.push_back('(');
  176. } else if (ch == ')') {
  177. while (charstack.back() != '(') {
  178. onceout();
  179. }
  180. charstack.pop_back();
  181. } else if (ch == '*') {
  182. while (charstack.size() && charstack.back() == '*') {
  183. onceout();
  184. }
  185. charstack.push_back(ch);
  186. } else {
  187. while (charstack.size() && (charstack.back() == '*' || charstack.back() == '+' || charstack.back() == '-')) {
  188. onceout();
  189. }
  190. charstack.push_back(ch);
  191. }
  192. }
  193. while (charstack.size()) {
  194. onceout();
  195. }
  196. head = valstack.back();
  197. ++altim;
  198. for (ul i = 1; i <= n; ++i) {
  199. li tmp;
  200. iss >> tmp;
  201. ans[0][i] = (tmp % li(mod) + mod) % mod;
  202. al[0][i] = altim;
  203. ans[1][i] = 1;
  204. al[1][i] = altim;
  205. for (ul j = 2; j <= 5; ++j) {
  206. ans[j][i] = 0;
  207. al[j][i] = altim;
  208. }
  209. }
  210. for (ul i = 0; i <= 5; ++i) {
  211. if (i) {
  212. oss << ' ';
  213. }
  214. oss << calc(i, head);
  215. }
  216. oss << '\n';
  217. tim = 0;
  218. g[head] = 1;
  219. search(head);
  220. for (ul i = 1; i <= head; ++i) {
  221. for (ul k = 1; (1 << k) <= i; ++k) {
  222. stleft[i][k] = std::max(stleft[i][k - 1], stleft[i - (1 << k - 1)][k - 1]);
  223. }
  224. }
  225. for (ul i = head; i >= 1; --i) {
  226. for (ul k = 1; i + (1 << k) - 1 <= head; ++k) {
  227. stright[i][k] = std::max(stright[i][k - 1], stright[i + (1 << k - 1)][k - 1]);
  228. }
  229. }
  230. ul m;
  231. iss >> m;
  232. for (ul qid = 1; qid <= m; ++qid) {
  233. ul t;
  234. iss >> t;
  235. for (ul i = 1; i <= t; ++i) {
  236. iss >> is[i];
  237. }
  238. std::sort(is + 1, is + t + 1, [](ul a, ul b){return dfn[a] < dfn[b];});
  239. num ans1, ans2;
  240. for (ul i = 1; i <= t; ++i) {
  241. ans1 = ans1 * g[is[i]];
  242. }
  243. bool flag = true;
  244. for (ul i = 1, j = 2; j <= t; ++i, ++j) {
  245. ul l = lca(is[i], is[j]);
  246. if (tree[l].op != '*') {
  247. flag = false;
  248. break;
  249. }
  250. ans2 = ans2 * g[l] * f[tree[l].left] * f[tree[l].right];
  251. }
  252. ul ans;
  253. if (!flag || ans1.cnt0 != ans2.cnt0) {
  254. ans = 0;
  255. } else {
  256. ans = mul(ans1.v, inverse(ans2.v));
  257. }
  258. oss << ans << '\n';
  259. }
  260. }
  261. std::cout << oss.str();
  262. return 0;
  263. }

E、Array Repairing 6818

首先,构成一个个点的有向基环树森林,可以发现,当时,消耗就是减去连通块的数量,而时,消耗就是减去连通块的数量加上叶子的数量。证明很容易,只需要说明两个对应概念在两种操作下的减小量和单步消耗的比值不超过一,且能达到。

叶子数量的期望值很容易求,现在考虑求连通块数量的期望值。用表示中满足连通块数量刚好是的数列的数量(),用表示中所有数列的数量。那么显然,其中
于是有如下关系:

于是

于是连通块数量期望值就是

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. using vul = std::vector<ul>;
  10. const ul base = 998244353;
  11. ul plus(ul a, ul b)
  12. {
  13. return a + b < base ? a + b : a + b - base;
  14. }
  15. ul minus(ul a, ul b)
  16. {
  17. return a < b ? a + base - b : a - b;
  18. }
  19. ul mul(ul a, ul b)
  20. {
  21. return ull(a) * ull(b) % base;
  22. }
  23. void exgcd(li a, li b, li& x, li& y)
  24. {
  25. if (b) {
  26. exgcd(b, a % b, y, x);
  27. y -= x * (a / b);
  28. } else {
  29. x = 1;
  30. y = 0;
  31. }
  32. }
  33. ul inverse(ul a)
  34. {
  35. li x, y;
  36. exgcd(a, base, x, y);
  37. return x < 0 ? x + li(base) : x;
  38. }
  39. ul pow(ul a, ul b)
  40. {
  41. ul ret = 1;
  42. ul temp = a;
  43. while (b) {
  44. if (b & 1) {
  45. ret = mul(ret, temp);
  46. }
  47. temp = mul(temp, temp);
  48. b >>= 1;
  49. }
  50. return ret;
  51. }
  52. class polynomial : public vul {
  53. public:
  54. void clearzero() {
  55. while (size() && !back()) {
  56. pop_back();
  57. }
  58. }
  59. polynomial()=default;
  60. polynomial(const vul& a): vul(a) { }
  61. polynomial(vul&& a): vul(std::move(a)) { }
  62. ul degree() const {
  63. return size() - 1;
  64. }
  65. ul operator()(ul x) const {
  66. ul ret = 0;
  67. for (ul i = size() - 1; ~i; --i) {
  68. ret = mul(ret, x);
  69. ret = plus(ret, vul::operator[](i));
  70. }
  71. return ret;
  72. }
  73. };
  74. polynomial& operator+=(polynomial& a, const polynomial& b)
  75. {
  76. a.resize(std::max(a.size(), b.size()), 0);
  77. for (ul i = 0; i != b.size(); ++i) {
  78. a[i] = plus(a[i], b[i]);
  79. }
  80. a.clearzero();
  81. return a;
  82. }
  83. polynomial operator+(const polynomial& a, const polynomial& b)
  84. {
  85. polynomial ret = a;
  86. return ret += b;
  87. }
  88. polynomial& operator-=(polynomial& a, const polynomial& b)
  89. {
  90. a.resize(std::max(a.size(), b.size()), 0);
  91. for (ul i = 0; i != b.size(); ++i) {
  92. a[i] = minus(a[i], b[i]);
  93. }
  94. a.clearzero();
  95. return a;
  96. }
  97. polynomial operator-(const polynomial& a, const polynomial& b)
  98. {
  99. polynomial ret = a;
  100. return ret -= b;
  101. }
  102. class ntt_t {
  103. public:
  104. static const ul lgsz = 20;
  105. static const ul sz = 1 << lgsz;
  106. static const ul g = 3;
  107. ul w[sz + 1];
  108. ul leninv[lgsz + 1];
  109. ntt_t() {
  110. ul wn = pow(g, (base - 1) >> lgsz);
  111. w[0] = 1;
  112. for (ul i = 1; i <= sz; ++i) {
  113. w[i] = mul(w[i - 1], wn);
  114. }
  115. leninv[lgsz] = inverse(sz);
  116. for (ul i = lgsz - 1; ~i; --i) {
  117. leninv[i] = plus(leninv[i + 1], leninv[i + 1]);
  118. }
  119. }
  120. void operator()(vul& v, ul& n, bool inv) {
  121. ul lgn = 0;
  122. while ((1 << lgn) < n) {
  123. ++lgn;
  124. }
  125. n = 1 << lgn;
  126. v.resize(n, 0);
  127. for (ul i = 0, j = 0; i != n; ++i) {
  128. if (i < j) {
  129. std::swap(v[i], v[j]);
  130. }
  131. ul k = n >> 1;
  132. while (k & j) {
  133. j &= ~k;
  134. k >>= 1;
  135. }
  136. j |= k;
  137. }
  138. for (ul lgmid = 0; (1 << lgmid) != n; ++lgmid) {
  139. ul mid = 1 << lgmid;
  140. ul len = mid << 1;
  141. for (ul i = 0; i != n; i += len) {
  142. for (ul j = 0; j != mid; ++j) {
  143. ul t0 = v[i + j];
  144. ul t1 = mul(w[inv ? (len - j << lgsz - lgmid - 1) : (j << lgsz - lgmid - 1)], v[i + j + mid]);
  145. v[i + j] = plus(t0, t1);
  146. v[i + j + mid] = minus(t0, t1);
  147. }
  148. }
  149. }
  150. if (inv) {
  151. for (ul i = 0; i != n; ++i) {
  152. v[i] = mul(v[i], leninv[lgn]);
  153. }
  154. }
  155. }
  156. } ntt;
  157. polynomial& operator*=(polynomial& a, const polynomial& b)
  158. {
  159. if (!b.size() || !a.size()) {
  160. a.resize(0);
  161. return a;
  162. }
  163. polynomial temp = b;
  164. ul npmp1 = a.size() + b.size() - 1;
  165. if (ull(a.size()) * ull(b.size()) <= ull(npmp1) * ull(50)) {
  166. temp.resize(0);
  167. temp.resize(npmp1, 0);
  168. for (ul i = 0; i != a.size(); ++i) {
  169. for (ul j = 0; j != b.size(); ++j) {
  170. temp[i + j] = plus(temp[i + j], mul(a[i], b[j]));
  171. }
  172. }
  173. a = temp;
  174. a.clearzero();
  175. return a;
  176. }
  177. ntt(a, npmp1, false);
  178. ntt(temp, npmp1, false);
  179. for (ul i = 0; i != npmp1; ++i) {
  180. a[i] = mul(a[i], temp[i]);
  181. }
  182. ntt(a, npmp1, true);
  183. a.clearzero();
  184. return a;
  185. }
  186. polynomial operator*(const polynomial& a, const polynomial& b)
  187. {
  188. polynomial ret = a;
  189. return ret *= b;
  190. }
  191. polynomial& operator*=(polynomial& a, ul b)
  192. {
  193. if (!b) {
  194. a.resize(0);
  195. return a;
  196. }
  197. for (ul i = 0; i != a.size(); ++i) {
  198. a[i] = mul(a[i], b);
  199. }
  200. return a;
  201. }
  202. polynomial operator*(const polynomial& a, ul b)
  203. {
  204. polynomial ret = a;
  205. return ret *= b;
  206. }
  207. polynomial inverse(const polynomial& a, ul lgdeg)
  208. {
  209. polynomial ret({inverse(a[0])});
  210. polynomial temp;
  211. polynomial tempa;
  212. for (ul i = 0; i != lgdeg; ++i) {
  213. tempa.resize(0);
  214. tempa.resize(1 << i << 1, 0);
  215. for (ul j = 0; j != tempa.size() && j != a.size(); ++j) {
  216. tempa[j] = a[j];
  217. }
  218. temp = ret * (polynomial({2}) - tempa * ret);
  219. if (temp.size() > (1 << i << 1)) {
  220. temp.resize(1 << i << 1, 0);
  221. }
  222. temp.clearzero();
  223. std::swap(temp, ret);
  224. }
  225. return ret;
  226. }
  227. polynomial diffrential(const polynomial& a)
  228. {
  229. if (!a.size()) {
  230. return a;
  231. }
  232. polynomial ret(vul(a.size() - 1, 0));
  233. for (ul i = 1; i != a.size(); ++i) {
  234. ret[i - 1] = mul(a[i], i);
  235. }
  236. return ret;
  237. }
  238. polynomial integral(const polynomial& a)
  239. {
  240. polynomial ret(vul(a.size() + 1, 0));
  241. for (ul i = 0; i != a.size(); ++i) {
  242. ret[i + 1] = mul(a[i], inverse(i + 1));
  243. }
  244. return ret;
  245. }
  246. polynomial ln(const polynomial& a, ul lgdeg)
  247. {
  248. polynomial da = diffrential(a);
  249. polynomial inva = inverse(a, lgdeg);
  250. polynomial ret = integral(da * inva);
  251. if (ret.size() > (1 << lgdeg)) {
  252. ret.resize(1 << lgdeg);
  253. ret.clearzero();
  254. }
  255. return ret;
  256. }
  257. const ul maxn = 5e5;
  258. ul fac[maxn + 1];
  259. ul fiv[maxn + 1];
  260. int main()
  261. {
  262. std::ios::sync_with_stdio(false);
  263. std::cin.tie(0);
  264. iss.tie(0);
  265. oss.tie(0);
  266. std::getline(std::cin, instr, char(0));
  267. iss.str(instr);
  268. ul n;
  269. iss >> n;
  270. fac[0] = 1;
  271. for (ul i = 1; i <= n; ++i) {
  272. fac[i] = mul(fac[i - 1], i);
  273. }
  274. fiv[n] = inverse(fac[n]);
  275. for (ul i = n; i >= 1; --i) {
  276. fiv[i - 1] = mul(fiv[i], i);
  277. }
  278. polynomial g(vul(n + 1));
  279. g[0] = 1;
  280. for (ul i = 1; i <= n; ++i) {
  281. g[i] = mul(fiv[i], pow(i, i));
  282. }
  283. polynomial f = ln(g, 32 - __builtin_clz(n));
  284. f.resize(n + 1);
  285. polynomial h = f * g;
  286. h.resize(n + 1);
  287. for (ul i = 1; i <= n; ++i) {
  288. ul tmp = mul(h[i], fac[i]);
  289. ul tmp2 = inverse(mul(g[i], fac[i]));
  290. oss << "0 " << minus(i, mul(tmp, tmp2)) << ' ' << plus(minus(i, mul(tmp, tmp2)), mul(mul(pow(i - 1, i), tmp2), i)) << '\n';
  291. }
  292. std::cout << oss.str();
  293. return 0;
  294. }

F、Alice and Bob 6819

官方题解如下,很清楚:
无标题.png-248kB

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. const ul maxn = 1e5;
  10. ul T;
  11. ul n, v, q, k;
  12. ul stack[maxn + 1];
  13. ul cnt;
  14. ul num[maxn + 1];
  15. ul al[maxn + 1];
  16. int main()
  17. {
  18. std::ios::sync_with_stdio(false);
  19. std::cin.tie(0);
  20. iss.tie(0);
  21. oss.tie(0);
  22. std::getline(std::cin, instr, char(0));
  23. iss.str(instr);
  24. iss >> T;
  25. for (ul Case = 1; Case <= T; ++Case) {
  26. iss >> n >> v >> q >> k;
  27. cnt = 0;
  28. for (ul i = 1; i <= q; ++i) {
  29. ul tmp;
  30. iss >> tmp;
  31. al[tmp] = Case;
  32. ul it = std::lower_bound(stack + 1, stack + cnt + 1, tmp) - stack;
  33. cnt = std::max(cnt, it);
  34. stack[it] = tmp;
  35. }
  36. std::memset(num + 1, 0, k * sizeof(ul));
  37. for (ul i = 1; i <= n; ++i) {
  38. if (al[i] != Case) {
  39. ul it = std::lower_bound(stack + 1, stack + cnt + 1, i) - stack;
  40. ++num[it];
  41. }
  42. }
  43. if (v == 1) {
  44. if (num[k] > 0) {
  45. oss << "YES " << num[k] << '\n';
  46. } else {
  47. ul sum = 0;
  48. for (ul i = 1; i + 1 <= k; ++i) {
  49. sum += num[i];
  50. }
  51. if (sum & 1) {
  52. oss << "YES " << sum - num[k - 1] + (num[k - 1] > 0) << '\n';
  53. } else {
  54. oss << "NO\n";
  55. }
  56. }
  57. } else {
  58. if (num[k - 1] >= 2) {
  59. oss << "YES 1\n";
  60. } else {
  61. ul sum = 0;
  62. for (ul i = 1; i + 1 <= k; ++i) {
  63. sum += num[i];
  64. }
  65. if (sum & 1) {
  66. oss << "YES " << (num[k - 1] ? 1 + (num[k - 2] > 0) : (num[k - 2] > 0) + (num[k - 2] > 1)) + sum - num[k - 1] - num[k - 2] << '\n';
  67. } else {
  68. oss << "NO\n";
  69. }
  70. }
  71. }
  72. }
  73. std::cout << oss.str();
  74. return 0;
  75. }

G、Tree 6820

简单题

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. using pullull = std::pair<ull, ull>;
  10. const ul maxn = 2e5;
  11. ul T;
  12. ul n, k;
  13. class edge_t {
  14. public:
  15. ul to = 0;
  16. ul d = 0;
  17. edge_t()=default;
  18. edge_t(ul a, ul b): to(a), d(b) {}
  19. };
  20. std::vector<edge_t> edge[maxn + 1];
  21. ull ans[maxn + 1][5];
  22. ull outans;
  23. void search(ul curr, ul prev)
  24. {
  25. static std::vector<pullull> stack;
  26. for (const auto& e : edge[curr]) {
  27. ul next = e.to;
  28. if (next == prev) {
  29. continue;
  30. }
  31. search(next, curr);
  32. }
  33. stack.resize(0);
  34. for (const auto& e : edge[curr]) {
  35. ul next = e.to;
  36. if (next == prev) {
  37. continue;
  38. }
  39. stack.push_back(pullull(e.d + ans[next][0], e.d + ans[next][6]));
  40. }
  41. std::sort(stack.rbegin(), stack.rend());
  42. ans[curr][0] = ans[curr][7] = ans[curr][8] = ans[curr][9] = 0;
  43. for (ul i = 0; i + 1 < k && i != stack.size(); ++i) {
  44. ans[curr][0] += stack[i].first;
  45. }
  46. for (ul i = 0; i < k && i != stack.size(); ++i) {
  47. ans[curr][10] += stack[i].first;
  48. }
  49. if (k >= 1) {
  50. for (ul i = 0; i != stack.size(); ++i) {
  51. ans[curr][11] += stack[i].first;
  52. ans[curr][12] += stack[i].first;
  53. }
  54. }
  55. if (k >= 2) {
  56. ull tmp = 0;
  57. for (ul i = 0; i != k - 2 && i != stack.size(); ++i) {
  58. tmp += stack[i].first;
  59. }
  60. ull tmp2 = 0;
  61. for (ul i = k - 2; i < stack.size(); ++i) {
  62. tmp2 = std::max(tmp2, stack[i].second);
  63. }
  64. tmp += tmp2;
  65. tmp2 = 0;
  66. ull tmp3 = 0;
  67. for (ul i = 0; i != k - 1 && i != stack.size(); ++i) {
  68. tmp2 += stack[i].first;
  69. tmp3 = std::max(tmp3, stack[i].second - stack[i].first);
  70. }
  71. tmp = std::max(tmp, tmp3 + tmp2);
  72. ans[curr][13] = std::max(ans[curr][14], tmp);
  73. }
  74. if (k >= 1) {
  75. ull tmp = 0;
  76. for (ul i = 0; i != k - 1 && i != stack.size(); ++i) {
  77. tmp += stack[i].first;
  78. }
  79. ull tmp2 = 0;
  80. for (ul i = k - 1; i < stack.size(); ++i) {
  81. tmp2 = std::max(tmp2, stack[i].second);
  82. }
  83. tmp += tmp2;
  84. tmp2 = 0;
  85. ull tmp3 = 0;
  86. for (ul i = 0; i != k && i != stack.size(); ++i) {
  87. tmp2 += stack[i].first;
  88. tmp3 = std::max(tmp3, stack[i].second - stack[i].first);
  89. }
  90. tmp = std::max(tmp, tmp3 + tmp2);
  91. ans[curr][15] = std::max(ans[curr][16], tmp);
  92. }
  93. outans = std::max(outans, ans[curr][17]);
  94. outans = std::max(outans, ans[curr][18]);
  95. }
  96. int main()
  97. {
  98. std::ios::sync_with_stdio(false);
  99. std::cin.tie(0);
  100. iss.tie(0);
  101. oss.tie(0);
  102. std::getline(std::cin, instr, char(0));
  103. iss.str(instr);
  104. iss >> T;
  105. for (ul Case = 1; Case <= T; ++Case) {
  106. iss >> n >> k;
  107. for (ul i = 1; i <= n; ++i) {
  108. edge[i].resize(0);
  109. }
  110. for (ul i = 1; i <= n - 1; ++i) {
  111. ul u, v, d;
  112. iss >> u >> v >> d;
  113. edge[u].push_back(edge_t(v, d));
  114. edge[v].push_back(edge_t(u, d));
  115. }
  116. if (!k) {
  117. oss << "0\n";
  118. continue;
  119. }
  120. outans = 0;
  121. search(1, 0);
  122. oss << outans << '\n';
  123. }
  124. std::cout << oss.str();
  125. return 0;
  126. }

H、Set2 6821

表示在有个数的情况,存活的概率,递推即可。

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. const ul mod = 998244353;
  10. ul plus(ul a, ul b)
  11. {
  12. return a + b < mod ? a + b : a + b - mod;
  13. }
  14. ul minus(ul a, ul b)
  15. {
  16. return a < b ? a + mod - b : a - b;
  17. }
  18. ul mul(ul a, ul b)
  19. {
  20. return ull(a) * ull(b) % mod;
  21. }
  22. void exgcd(li a, li b, li& x, li& y)
  23. {
  24. if (b) {
  25. exgcd(b, a % b, y, x);
  26. y -= a / b * x;
  27. } else {
  28. x = 1;
  29. y = 0;
  30. }
  31. }
  32. ul inverse(ul a)
  33. {
  34. li x, y;
  35. exgcd(a, mod, x, y);
  36. return x < 0 ? x + li(mod) : x;
  37. }
  38. const ul maxn = 5e3;
  39. ul T, n, k;
  40. ul fac[maxn + 1];
  41. ul fiv[maxn + 1];
  42. ul ans[maxn + 1][maxn + 1];
  43. ul bi(ul a, ul b)
  44. {
  45. return mul(fac[a], mul(fiv[a - b], fiv[b]));
  46. }
  47. ul biv(ul a, ul b)
  48. {
  49. return mul(fiv[a], mul(fac[a - b], fac[b]));
  50. }
  51. int main()
  52. {
  53. std::ios::sync_with_stdio(false);
  54. std::cin.tie(0);
  55. iss.tie(0);
  56. oss.tie(0);
  57. std::getline(std::cin, instr, char(0));
  58. iss.str(instr);
  59. fac[0] = 1;
  60. for (ul i = 1; i <= maxn; ++i) {
  61. fac[i] = mul(fac[i - 1], i);
  62. }
  63. fiv[maxn] = inverse(fac[maxn]);
  64. for (ul i = maxn; i >= 1; --i) {
  65. fiv[i - 1] = mul(fiv[i], i);
  66. }
  67. iss >> T;
  68. for (ul Case = 1; Case <= T; ++Case) {
  69. iss >> n >> k;
  70. ul alpha = n % (k + 1);
  71. for (ul i = 1; i <= alpha; ++i) {
  72. ans[alpha][i] = 1;
  73. }
  74. for (ul r = alpha + k + 1; r <= n; r += k + 1) {
  75. ans[r][19] = 0;
  76. ul tmp = biv(r - 1, k);
  77. for (ul i = 2; i <= r; ++i) {
  78. ans[r][i] = 0;
  79. for (ul j = std::max(k + i, r) - r; j <= std::min(k, i - 2); ++j) {
  80. ans[r][i] = plus(ans[r][i], mul(ans[r - k - 1][i - j - 1], mul(bi(i - 2, j), bi(r - i, k - j))));
  81. }
  82. ans[r][i] = mul(ans[r][i], tmp);
  83. }
  84. }
  85. for (ul i = 1; i <= n; ++i) {
  86. if (i != 1) {
  87. oss << ' ';
  88. }
  89. oss << ans[n][i];
  90. }
  91. oss << '\n';
  92. }
  93. std::cout << oss.str();
  94. return 0;
  95. }

I、Paperfolding 6822

倒着考虑,每当上下展开的时候,行数变为原先两倍减一,每当左右展开的时候,列数变为原先两倍减一。

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. const ul mod = 998244353;
  10. ul plus(ul a, ul b)
  11. {
  12. return a + b < mod ? a + b : a + b - mod;
  13. }
  14. ul minus(ul a, ul b)
  15. {
  16. return a < b ? a + mod - b : a - b;
  17. }
  18. ul mul(ul a, ul b)
  19. {
  20. return ull(a) * ull(b) % mod;
  21. }
  22. void exgcd(li a, li b, li& x, li& y)
  23. {
  24. if (b) {
  25. exgcd(b, a % b, y, x);
  26. y -= a / b * x;
  27. } else {
  28. x = 1;
  29. y = 0;
  30. }
  31. }
  32. ul inverse(ul a)
  33. {
  34. li x, y;
  35. exgcd(a, mod, x, y);
  36. return x < 0 ? x + li(mod) : x;
  37. }
  38. ul pow(ul a, ul b)
  39. {
  40. ul ret = 1;
  41. while (b) {
  42. if (b & 1) {
  43. ret = mul(ret, a);
  44. }
  45. a = mul(a, a);
  46. b >>= 1;
  47. }
  48. return ret;
  49. }
  50. ul inv2 = inverse(2);
  51. ul T;
  52. ull n;
  53. int main()
  54. {
  55. std::ios::sync_with_stdio(false);
  56. std::cin.tie(0);
  57. iss.tie(0);
  58. oss.tie(0);
  59. std::getline(std::cin, instr, char(0));
  60. iss.str(instr);
  61. iss >> T;
  62. for (ul Case = 1; Case <= T; ++Case) {
  63. iss >> n;
  64. n %= mod - 1;
  65. oss << plus(plus(pow(2, ul(n)), mul(mul(pow(3, ul(n)), 2), pow(inv2, ul(n)))), 1) << '\n';
  66. }
  67. std::cout << oss.str();
  68. return 0;
  69. }

J、Function 6823

题意实际就是要求作为的线性变换,其若当型中所有若当块形如
于是构造就很容易了。关键是检查,检查详细步骤会在代码中注释出来,关于此检查步骤的必要性和充分性请自己证明。

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. ul T;
  10. ul n, m;
  11. const ul maxd = 60;
  12. const ul maxm = 2e5;
  13. std::vector<ull> base;
  14. char op[20];
  15. char so[40];
  16. class xy {
  17. public:
  18. ull x = 0;
  19. ll y = 0;
  20. };
  21. std::vector<xy> base2;
  22. std::vector<xy> base3;
  23. xy s;
  24. std::vector<ull> tmp;
  25. std::vector<ull> base4;
  26. int main()
  27. {
  28. std::ios::sync_with_stdio(false);
  29. std::cin.tie(0);
  30. iss.tie(0);
  31. oss.tie(0);
  32. std::getline(std::cin, instr, char(0));
  33. iss.str(instr);
  34. iss >> T;
  35. for (ul Case = 1; Case <= T; ++Case) {
  36. iss >> n;
  37. base.resize(0);
  38. for (ul i = 1; i <= n; ++i) {
  39. ull a;
  40. iss >> a;
  41. for (auto v : base) {
  42. a = std::min(a, a ^ v);
  43. }
  44. if (a) {
  45. base.push_back(a);
  46. }
  47. }
  48. iss >> op + 1;
  49. if (op[2] == 'o') {
  50. if (base.size() & 1) {
  51. oss << "NoSolution\n";
  52. iss >> m;
  53. for (ul c = 1; c <= m; ++c) {
  54. ull x;
  55. iss >> x;
  56. }
  57. continue;
  58. } else {
  59. oss << "HaveSolution\n";
  60. iss >> m;
  61. ul t = base.size() >> 1;
  62. for (ul c = 1; c <= m; ++c) {
  63. ull x;
  64. ull y = 0;
  65. iss >> x;
  66. for (ul i = 0; i != t; ++i) {
  67. if ((x ^ base[i]) < x) {
  68. x ^= base[i];
  69. y ^= base[i + t];
  70. }
  71. }
  72. for (ul i = t; i != base.size(); ++i) {
  73. x = std::min(x, x ^ base[i]);
  74. }
  75. if (x) {
  76. oss << "-1\n";
  77. } else {
  78. oss << y << '\n';
  79. }
  80. }
  81. }
  82. } else {
  83. iss >> so + 1;
  84. if (base.size() & 1) {//如果S(a)维度为奇数,显然不可行
  85. if (so[1] == 'N') {
  86. oss << "Yes\n";
  87. continue;
  88. } else {
  89. oss << "No\n";
  90. iss >> m;
  91. for (ul c = 1; c <= m; ++c) {
  92. ull x;
  93. ll y;
  94. iss >> x >> y;
  95. }
  96. continue;
  97. }
  98. } else {
  99. if (so[1] == 'N') {//如果维度为偶数,显然可行
  100. oss << "No\n";
  101. continue;
  102. } else {
  103. iss >> m;
  104. ul t = base.size() >> 1;
  105. bool flag = true;
  106. base2.resize(0);
  107. for (ul c = 1; c <= m; ++c) {
  108. iss >> s.x >> s.y;
  109. if (!flag) {
  110. continue;
  111. }
  112. if (s.y == -1) {//确认x是不是确实在S(a)外
  113. for (auto v : base) {
  114. s.x = std::min(s.x ^ v, s.x);
  115. }
  116. if (s.x == 0) {
  117. flag = false;
  118. }
  119. continue;
  120. }
  121. for (const auto& v : base2) {//保证不丢失信息的情况下,检查f的线性性
  122. if ((s.x ^ v.x) < s.x) {
  123. s.x ^= v.x;
  124. s.y ^= v.y;
  125. }
  126. }
  127. if (s.x == 0 && s.y != 0) {
  128. flag = false;
  129. continue;
  130. }
  131. if (s.x) {
  132. base2.push_back(s);
  133. }
  134. }
  135. if (!flag) {
  136. oss << "No\n";
  137. continue;
  138. }
  139. for (auto s : base2) {//检查是否所有插值点的输入和输出都在S(a)中
  140. for (auto v : base) {
  141. s.x = std::min(s.x, s.x ^ v);
  142. }
  143. for (auto v : base) {
  144. s.y = std::min(ull(s.y), s.y ^ v);
  145. }
  146. if (s.x || s.y) {
  147. flag = false;
  148. break;
  149. }
  150. }
  151. if (!flag) {
  152. oss << "No\n";
  153. continue;
  154. }
  155. base3.resize(0);
  156. tmp.resize(0);
  157. for (auto s : base2) {//在不丢失信息的情况下,求出y所张成的子空间(也就是插值点间接提供的核子空间,由于要求f(y)=0),并确认插值点直接提供的核子空间
  158. for (auto v : base3) {
  159. if ((s.y ^ v.y) < s.y) {
  160. s.y ^= v.y;
  161. s.x ^= v.x;
  162. }
  163. }
  164. if (s.y) {
  165. base3.push_back(s);
  166. } else {
  167. tmp.push_back(s.x);
  168. }
  169. }
  170. base4.resize(0);
  171. for (auto s : base3) {//接下来两个for将使得base4就是插值点直接以及间接给出的核子空间
  172. base4.push_back(s.y);
  173. }
  174. for (auto s : tmp) {
  175. for (auto v : base4) {
  176. s = std::min(s, s ^ v);
  177. }
  178. if (s) {
  179. base4.push_back(s);
  180. }
  181. }
  182. if (base4.size() * 2 > base.size()) {//如果核子空间的维度大于了S(a)维度的一半,肯定不行
  183. flag = false;
  184. }
  185. if (!flag) {
  186. oss << "No\n";
  187. continue;
  188. }
  189. for (auto s : base3) {//最后,再检查那些x和y是否独立(这是关键要完成的证明,必要性就是说明这些如果不独立则肯定不行,充分性就是说明这些如果独立就一定能张出合适的f)
  190. for (auto v : base4) {
  191. s.x = std::min(s.x, s.x ^ v);
  192. }
  193. if (s.x) {
  194. base4.push_back(s.x);
  195. } else {
  196. flag = false;
  197. break;
  198. }
  199. }
  200. if (!flag) {
  201. oss << "No\n";
  202. continue;
  203. }
  204. oss << "Yes\n";
  205. }
  206. }
  207. }
  208. }
  209. std::cout << oss.str();
  210. return 0;
  211. }

K、Exam 6824

2SAT,线段树建图

  1. #include <bits/stdc++.h>
  2. namespace fast_pool {
  3. constexpr size_t const size = 481 << 20;
  4. unsigned char data[size];
  5. unsigned char* ptr = data;
  6. void clear() {ptr = data;}
  7. void* fast_alloc(size_t n) {ptr += n; return ptr - n;}
  8. };
  9. template<class T>
  10. class myallocator {
  11. public:
  12. typedef T value_type;
  13. typedef value_type* pointer;
  14. typedef value_type& reference;
  15. typedef value_type const* const_pointer;
  16. typedef value_type const& const_reference;
  17. typedef size_t size_type;
  18. typedef ptrdiff_t difference_type;
  19. pointer allocate(size_t n, const T* pHint = 0) {
  20. return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));
  21. }
  22. void deallocate(pointer p, size_type n) {}
  23. void destroy(T* p) {p->~T();}
  24. void construct(T* p, const T& val) {::new((void *)p) T(val);}
  25. size_t max_size() const throw() {
  26. return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);
  27. }
  28. T* address(T& val) const {return &val;}
  29. const T* address(const T& val) const {return &val;}
  30. myallocator() throw() {}
  31. myallocator(const T* p) throw() {}
  32. ~myallocator() throw() {}
  33. template <typename _other> struct rebind { typedef myallocator<_other> other; };
  34. };
  35. std::stringstream iss;
  36. std::stringstream oss;
  37. std::string instr;
  38. using ul = std::uint32_t;
  39. using li = std::int32_t;
  40. using ull = std::uint64_t;
  41. using ll = std::int64_t;
  42. ul T;
  43. ul n;
  44. const ul maxn = 25000;
  45. class seg_t {
  46. public:
  47. ul l = 0;
  48. ul r = 0;
  49. seg_t()=default;
  50. };
  51. class exam_t {
  52. public:
  53. seg_t a;
  54. seg_t b;
  55. exam_t()=default;
  56. };
  57. exam_t exam[maxn + 1];
  58. std::pair<seg_t, ul> props[maxn * 2 + 1];
  59. const ul maxsz = 1 << 16;
  60. ul sz;
  61. ul cnt;
  62. ul down[maxsz << 1];
  63. ul up[maxsz << 1];
  64. std::vector<ul, myallocator<ul>> edges[199959];
  65. void addedge(ul l, ul r, ul pid)
  66. {
  67. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  68. if (~l & 1) {
  69. edges[up[l ^ 1]].push_back(pid * 2);
  70. edges[pid * 2 - 1].push_back(down[l ^ 1]);
  71. }
  72. if (r & 1) {
  73. edges[up[r ^ 1]].push_back(pid * 2);
  74. edges[pid * 2 - 1].push_back(down[r ^ 1]);
  75. }
  76. }
  77. }
  78. ul low[199959];
  79. ul dfn[199959];
  80. std::vector<ul, myallocator<ul>> stack(199958);
  81. std::vector<bool> instack(199959);
  82. ul tim;
  83. void search(ul v, const std::vector<ul, myallocator<ul>> edges[], std::vector<std::vector<ul, myallocator<ul>>, myallocator<std::vector<ul, myallocator<ul>>>>& sccs)
  84. {
  85. low[v] = dfn[v] = ++tim;
  86. stack.push_back(v);
  87. instack[v] = true;
  88. for (ul w : edges[v]) {
  89. if (!dfn[w]) {
  90. search(w, edges, sccs);
  91. low[v] = std::min(low[v], low[w]);
  92. } else if (dfn[w] < dfn[v]) {
  93. if (instack[w]) {
  94. low[v] = std::min(low[v], dfn[w]);
  95. }
  96. }
  97. }
  98. if (low[v] == dfn[v]) {
  99. sccs.push_back(std::vector<ul, myallocator<ul>>());
  100. while (stack.size() && dfn[stack.back()] >= dfn[v]) {
  101. instack[stack.back()] = false;
  102. sccs.back().push_back(stack.back());
  103. stack.pop_back();
  104. }
  105. }
  106. }
  107. void scc(const std::vector<ul, myallocator<ul>> edges[], ul sz, std::vector<std::vector<ul, myallocator<ul>>, myallocator<std::vector<ul, myallocator<ul>>>>& sccs)
  108. {
  109. sccs.resize(0);
  110. tim = 0;
  111. stack.resize(0);
  112. instack.resize(0);
  113. instack.resize(sz + 1, false);
  114. std::memset(dfn + 1, 0, sz * sizeof(ul));
  115. for (ul w = 1; w <= sz; ++w) {
  116. if (!dfn[w]) {
  117. search(w, edges, sccs);
  118. }
  119. }
  120. }
  121. std::vector<std::vector<ul, myallocator<ul>>, myallocator<std::vector<ul, myallocator<ul>>>> sccs;
  122. ul already[maxn + maxn + maxn + maxn + 1];
  123. ul altim = 0;
  124. int main()
  125. {
  126. std::ios::sync_with_stdio(false);
  127. std::cin.tie(0);
  128. iss.tie(0);
  129. oss.tie(0);
  130. std::getline(std::cin, instr, char(0));
  131. iss.str(instr);
  132. iss >> T;
  133. for (ul Case = 1; Case <= T; ++Case) {
  134. iss >> n;
  135. ul mx = 0, mn = 0;
  136. for (ul i = 1; i <= n; ++i) {
  137. iss >> exam[i].a.l >> exam[i].a.r >> exam[i].b.l >> exam[i].b.r;
  138. exam[i].a.r += exam[i].a.l;
  139. exam[i].b.r += exam[i].b.l;
  140. mx = std::max(mx, std::max(exam[i].a.r, exam[i].b.r));
  141. mn = std::max(mn, std::min(exam[i].a.r, exam[i].b.r));
  142. props[i * 2 - 1] = std::pair<seg_t, ul>(exam[i].a, i * 2 - 1);
  143. props[i * 2] = std::pair<seg_t, ul>(exam[i].b, i * 2);
  144. }
  145. std::sort(props + 1, props + 2 * n + 1, [](const std::pair<seg_t, ul>& a, const std::pair<seg_t, ul>& b){return a.first.l < b.first.l;});
  146. sz = 1;
  147. ul lgsz = 0;
  148. while (n * 2 + 2 > sz) {
  149. sz <<= 1;
  150. ++lgsz;
  151. }
  152. cnt = n * 4;
  153. std::memset(down, 0, (sz << 1) * sizeof(ul));
  154. std::memset(up, 0, (sz << 1) * sizeof(ul));
  155. for (ul depth = 0; (1 << depth) < sz; ++depth) {
  156. for (ul i = 0; i != (1 << depth); ++i) {
  157. ul l = i << lgsz - depth;
  158. ul r = (i + 1 << lgsz - depth) - 1;
  159. if (l < 1 || r > 2 * n) {
  160. continue;
  161. }
  162. ++cnt;
  163. down[1 << depth | i] = cnt;
  164. ++cnt;
  165. up[1 << depth | i] = cnt;
  166. }
  167. }
  168. for (ul i = 1; i <= n + n; ++i) {
  169. down[sz | i] = props[i].second * 2;
  170. up[sz | i] = props[i].second * 2 - 1;
  171. }
  172. for (ul i = 1; i <= cnt; ++i) {
  173. edges[i].resize(0);
  174. }
  175. for (ul i = 1; i <= n; ++i) {
  176. edges[i * 4 - 2].push_back(i * 4 - 1);
  177. edges[i * 4].push_back(i * 4 - 3);
  178. }
  179. for (ul i = 1; i != sz; ++i) {
  180. if (!down[i]) {
  181. continue;
  182. }
  183. edges[down[i]].push_back(down[i << 1]);
  184. edges[down[i]].push_back(down[i << 1 | 1]);
  185. edges[up[i << 1]].push_back(up[i]);
  186. edges[up[i << 1 | 1]].push_back(up[i]);
  187. }
  188. for (ul i = 1; i <= n + n; ++i) {
  189. ul it1 = std::lower_bound(props + 1, props + i, props[i], [](const std::pair<seg_t, ul>& a, const std::pair<seg_t, ul>& b){return a.first.l < b.first.l;}) - props;
  190. auto tmp = props[i];
  191. tmp.first.l = tmp.first.r;
  192. ul it2 = std::upper_bound(props + i + 1, props + n + n + 1, tmp, [](const std::pair<seg_t, ul>& a, const std::pair<seg_t, ul>& b){return a.first.l < b.first.l;}) - props - 1;
  193. addedge(it1, i - 1, props[i].second);
  194. addedge(i + 1, it2, props[i].second);
  195. }
  196. ul l = mn - 1, r = mx + 1;
  197. while (l + 1 != r) {
  198. ul mid = l + r >> 1;
  199. for (ul i = 1; i <= n + n; ++i) {
  200. if (props[i].first.r > mid) {
  201. edges[props[i].second * 2 - 1].push_back(props[i].second * 2);
  202. }
  203. }
  204. scc(edges, cnt, sccs);
  205. bool flag = true;
  206. for (auto& scc : sccs) {
  207. ++altim;
  208. for (auto v : scc) {
  209. if (v > n * 4) {
  210. continue;
  211. }
  212. if ((v & 1) && already[v + 1] == altim || (~v & 1) && already[v - 1] == altim) {
  213. flag = false;
  214. break;
  215. }
  216. already[v] = altim;
  217. }
  218. if (!flag) {
  219. break;
  220. }
  221. }
  222. if (flag) {
  223. r = mid;
  224. } else {
  225. l = mid;
  226. }
  227. for (ul i = 1; i <= n + n; ++i) {
  228. if (props[i].first.r > mid) {
  229. edges[props[i].second * 2 - 1].pop_back();
  230. }
  231. }
  232. }
  233. oss << (r != mx + 1 ? li(r) : li(-1)) << '\n';
  234. }
  235. std::cout << oss.str();
  236. return 0;
  237. }

L、Set1 6825

官方题解如下:
无标题2.png-83.6kB
注意,图片中少除以了一样东西,很容易看出来。

  1. #include <bits/stdc++.h>
  2. std::stringstream iss;
  3. std::stringstream oss;
  4. std::string instr;
  5. using ul = std::uint32_t;
  6. using li = std::int32_t;
  7. using ull = std::uint64_t;
  8. using ll = std::int64_t;
  9. ul T;
  10. ul n;
  11. const ul mod = 998244353;
  12. ul plus(ul a, ul b)
  13. {
  14. return a + b < mod ? a + b : a + b - mod;
  15. }
  16. ul mul(ul a, ul b)
  17. {
  18. return ull(a) * ull(b) % mod;
  19. }
  20. void exgcd(li a, li b, li& x, li& y)
  21. {
  22. if (b) {
  23. exgcd(b, a % b, y, x);
  24. y -= a / b * x;
  25. } else {
  26. x = 1;
  27. y = 0;
  28. }
  29. }
  30. ul inverse(ul a)
  31. {
  32. li x, y;
  33. exgcd(a, mod, x, y);
  34. return x < 0 ? x + li(mod) : x;
  35. }
  36. const ul maxn = 5e6;
  37. ul fac[maxn + 1];
  38. ul fiv[maxn + 1];
  39. ul twopow[maxn + 1];
  40. ul twopowinv[maxn + 1];
  41. int main()
  42. {
  43. std::ios::sync_with_stdio(false);
  44. std::cin.tie(0);
  45. iss.tie(0);
  46. oss.tie(0);
  47. std::getline(std::cin, instr, char(0));
  48. iss.str(instr);
  49. fac[0] = 1;
  50. twopow[0] = 1;
  51. for (ul i = 1; i <= maxn; ++i) {
  52. fac[i] = mul(fac[i - 1], i);
  53. twopow[i] = plus(twopow[i - 1], twopow[i - 1]);
  54. }
  55. fiv[maxn] = inverse(fac[maxn]);
  56. twopowinv[maxn] = inverse(twopow[maxn]);
  57. for (ul i = maxn; i >= 1; --i) {
  58. fiv[i - 1] = mul(fiv[i], i);
  59. twopowinv[i - 1] = plus(twopowinv[i], twopowinv[i]);
  60. }
  61. iss >> T;
  62. for (ul Case = 1; Case <= T; ++Case) {
  63. iss >> n;
  64. ul lambda = mul(fiv[n >> 1], twopowinv[n >> 1]);
  65. ul sum = 0;
  66. for (ul i = 1; i <= n; ++i) {
  67. if (i != 1) {
  68. oss << ' ';
  69. }
  70. if (n - i > i - 1) {
  71. oss << '0';
  72. continue;
  73. }
  74. oss << mul(mul(mul(fac[i - 1], twopowinv[i - (n + 1 >> 1)]), fiv[i - (n + 1 >> 1)]), lambda);
  75. }
  76. oss << '\n';
  77. }
  78. std::cout << oss.str();
  79. return 0;
  80. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注