[关闭]
@qq290637843 2020-11-02T06:40:22.000000Z 字数 22039 阅读 280

2020杭电第八场

A、Auto-correction 6855

某种编辑距离。用表示变为的最小花费的有序对(第一个是替换总位数,第二个是替换总次数),那么显然

,设
那么
于是动态规划即可。

  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 = 2000, maxm = 4000;
  7. ul a[maxn + 1];
  8. ul b[maxm + 1];
  9. ul T;
  10. ul n, q, m;
  11. std::stringstream ss;
  12. std::string str;
  13. std::pair<li, li> operator+(const std::pair<li, li>& a, const std::pair<li, li>& b)
  14. {
  15. return std::pair<li, li>(a.first + b.first, a.second + b.second);
  16. }
  17. std::pair<li, li> operator-(const std::pair<li, li>& a, const std::pair<li, li>& b)
  18. {
  19. return std::pair<li, li>(a.first - b.first, a.second - b.second);
  20. }
  21. std::pair<li, li> f[maxn + 1][maxm + 1];
  22. std::pair<ul, ul> ffrom[maxn + 1][maxm + 1];
  23. std::pair<li, li> g[maxn + 1][maxm + 1];
  24. std::pair<ul, ul> gfrom[maxn + 1][maxm + 1];
  25. const li inf = 1e9;
  26. void initg(ul x, ul y)
  27. {
  28. g[x][y] = std::pair<li, li>(inf + 1, inf + 1);
  29. }
  30. void updateftog(ul fromx, ul fromy, ul tox, ul toy)
  31. {
  32. if (g[tox][toy] > f[fromx][fromy] - std::pair<li, li>(fromx, 0)) {
  33. g[tox][toy] = f[fromx][fromy] - std::pair<li, li>(fromx, 0);
  34. gfrom[tox][toy] = std::pair<ul, ul>(fromx, fromy);
  35. }
  36. }
  37. void updategtog(ul fromx, ul fromy, ul tox, ul toy)
  38. {
  39. if (g[tox][toy] > g[fromx][fromy]) {
  40. g[tox][toy] = g[fromx][fromy];
  41. gfrom[tox][toy] = gfrom[fromx][fromy];
  42. }
  43. }
  44. void initf(ul x, ul y)
  45. {
  46. f[x][y] = std::pair<li, li>(inf + 1, inf + 1);
  47. }
  48. void updatef(const std::pair<li, li>& v, ul fromx, ul fromy, ul tox, ul toy)
  49. {
  50. if (f[tox][toy] > v) {
  51. f[tox][toy] = v;
  52. ffrom[tox][toy] = std::pair<ul, ul>(fromx, fromy);
  53. }
  54. }
  55. int main()
  56. {
  57. std::scanf("%u", &T);
  58. for (ul Case = 1; Case <= T; ++Case) {
  59. std::scanf("%u%u", &n, &q);
  60. for (ul i = 1; i <= n; ++i) {
  61. std::scanf("%u", &a[i]);
  62. }
  63. std::getline(std::cin, str);
  64. ul acnt = 0;
  65. ul bcnt = 0;
  66. for (ul i = 1; i <= q; ++i) {
  67. std::getline(std::cin, str);
  68. ss.clear();
  69. ss.str(str);
  70. char ch;
  71. ss >> ch;
  72. if (ch == 'R') {
  73. ul l, r;
  74. ss >> l >> r;
  75. while (acnt + 1 < l) {
  76. ++bcnt;
  77. ++acnt;
  78. b[bcnt] = a[acnt];
  79. }
  80. ul t;
  81. while (ss >> t) {
  82. ++bcnt;
  83. b[bcnt] = t;
  84. }
  85. acnt = r;
  86. } else if (ch == 'D') {
  87. ul l, r;
  88. ss >> l >> r;
  89. while (acnt + 1 < l) {
  90. ++bcnt;
  91. ++acnt;
  92. b[bcnt] = a[acnt];
  93. }
  94. acnt = r;
  95. } else if (ch == 'A') {
  96. ul l;
  97. ss >> l;
  98. while (acnt + 1 < l) {
  99. ++bcnt;
  100. ++acnt;
  101. b[bcnt] = a[acnt];
  102. }
  103. ul t;
  104. while (ss >> t) {
  105. ++bcnt;
  106. b[bcnt] = t;
  107. }
  108. }
  109. }
  110. while (acnt + 1 <= n) {
  111. ++acnt;
  112. ++bcnt;
  113. b[bcnt] = a[acnt];
  114. }
  115. m = bcnt;
  116. f[0][0] = std::pair<li, li>(0, 0);
  117. initg(0, 0);
  118. updateftog(0, 0, 0, 0);
  119. for (ul y = 1; y <= m; ++y) {
  120. f[0][y] = std::pair<li, li>(inf, inf);
  121. initg(0, y);
  122. updateftog(0, y, 0, y);
  123. updategtog(0, y - 1, 0, y);
  124. }
  125. for (ul x = 1; x <= n; ++x) {
  126. f[x][0] = std::pair<li, li>(inf, inf);
  127. initg(x, 0);
  128. updateftog(x, 0, x, 0);
  129. updategtog(x - 1, 0, x, 0);
  130. for (ul y = 1; y <= m; ++y) {
  131. initf(x, y);
  132. updatef(g[x - 1][y - 1] + std::pair<li, li>(x, 1), gfrom[x - 1][y - 1].first, gfrom[x - 1][y - 1].second, x, y);
  133. if (a[x] == b[y]) {
  134. updatef(f[x - 1][y - 1], x - 1, y - 1, x, y);
  135. }
  136. initg(x, y);
  137. updateftog(x, y, x, y);
  138. updategtog(x - 1, y, x, y);
  139. updategtog(x, y - 1, x, y);
  140. }
  141. }
  142. std::printf("%d %d\n", f[n][m].first, f[n][m].second);
  143. ul x = n, y = m;
  144. while (x && y) {
  145. if (a[x] == b[y] && ffrom[x][y] == std::pair<ul, ul>(x - 1, y - 1)) {
  146. --x;
  147. --y;
  148. } else {
  149. ul px = ffrom[x][y].first;
  150. ul py = ffrom[x][y].second;
  151. std::printf("%u %u", px + ul(1), x);
  152. for (ul i = py + 1; i <= y; ++i) {
  153. std::printf(" %u", b[i]);
  154. }
  155. std::putchar('\n');
  156. x = px;
  157. y = py;
  158. }
  159. }
  160. }
  161. return 0;
  162. }

B、Breaking Down News 6856

表示前个新闻能拆出的最大收益。于是显然

其中。于是转移分为三种,来自大小关系的限制条件借助线段树解决,来自的限制条件借助在每个节点放单调队列解决。总计时间复杂度
为了解决常熟问题,自己弄了个allocator套在std::list里。

  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. using ul = std::uint32_t;
  36. using li = std::int32_t;
  37. using ull = std::uint64_t;
  38. using ll = std::int64_t;
  39. const ul maxn = 1e6;
  40. ul T;
  41. ul n, l, r;
  42. li a[maxn + 1];
  43. li s[maxn + 1];
  44. li f[maxn + 1];
  45. li mns = -li(n);
  46. li mxs = li(n);
  47. const ul mxsz = 1 << 20;
  48. std::list<std::pair<ul, li>, myallocator<std::pair<ul, li>>> tree[mxsz << 1];
  49. ul sz;
  50. void insert(ul pos, const std::pair<ul, li>& v)
  51. {
  52. for (pos |= sz; pos; pos >>= 1) {
  53. while (tree[pos].size() && tree[pos].back().second <= v.second) {
  54. tree[pos].pop_back();
  55. }
  56. tree[pos].push_back(v);
  57. }
  58. }
  59. void erase(ul pos, ul bound)
  60. {
  61. for (pos |= sz; pos; pos >>= 1) {
  62. while (tree[pos].size() && tree[pos].front().first < bound) {
  63. tree[pos].pop_front();
  64. }
  65. }
  66. }
  67. const li inf = 1e9;
  68. li query(ul l, ul r)
  69. {
  70. li ret = -inf;
  71. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  72. if (~l & 1) {
  73. if (tree[l ^ 1].size()) {
  74. ret = std::max(ret, tree[l ^ 1].front().second);
  75. }
  76. }
  77. if (r & 1) {
  78. if (tree[r ^ 1].size()) {
  79. ret = std::max(ret, tree[r ^ 1].front().second);
  80. }
  81. }
  82. }
  83. return ret;
  84. }
  85. int main()
  86. {
  87. std::scanf("%u", &T);
  88. for (ul Case = 1; Case <= T; ++Case) {
  89. std::scanf("%u%u%u", &n, &l, &r);
  90. mns = mxs = 0;
  91. for (ul i = 1; i <= n; ++i) {
  92. std::scanf("%d", &a[i]);
  93. s[i] = s[i - 1] + a[i];
  94. mns = std::min(mns, s[i]);
  95. mxs = std::max(mxs, s[i]);
  96. }
  97. sz = 1;
  98. while (sz < mxs - mns + 1 + 2) {
  99. sz <<= 1;
  100. }
  101. fast_pool::clear();
  102. f[0] = 0;
  103. for (ul i = 1; i <= n; ++i) {
  104. if (i >= r + 1) {
  105. erase(s[i - r - 1] - mns + 1, i - r);
  106. }
  107. if (i >= l) {
  108. insert(s[i - l] - mns + 1, std::pair<ul, li>(i - l, f[i - l]));
  109. }
  110. f[i] = -inf;
  111. f[i] = std::max(f[i], query(1, s[i] - 1 - mns + 1) + 1);
  112. f[i] = std::max(f[i], query(s[i] - mns + 1, s[i] - mns + 1));
  113. f[i] = std::max(f[i], query(s[i] + 1 - mns + 1, mxs - mns + 1) - 1);
  114. }
  115. for (ul i = n + 1; i <= n - l + r + 1; ++i) {
  116. erase(s[i - r - 1] - mns + 1, i - r);
  117. }
  118. std::printf("%d\n", f[n]);
  119. }
  120. return 0;
  121. }

C、Clockwise or Counterclockwise 6857

简单题

  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. class vec {
  8. public:
  9. ll x = 0;
  10. ll y = 0;
  11. };
  12. ll operator^(const vec& a, const vec& b)
  13. {
  14. return a.x * b.y - a.y * b.x;
  15. }
  16. vec a, b, c;
  17. int main()
  18. {
  19. std::scanf("%u", &T);
  20. for (ul Case = 1; Case <= T; ++Case) {
  21. std::scanf("%lld%lld%lld%lld%lld%lld", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y);
  22. std::printf((a ^ b) + (b ^ c) + (c ^ a) > 0 ? "Counterclockwise\n" : "Clockwise\n");
  23. }
  24. return 0;
  25. }

D、Discovery of Cycles 6858

连割树测板题。

  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 = 3e5;
  7. inline void swap(register ul& a, register ul& b)
  8. {
  9. a ^= b ^= a ^= b;
  10. }
  11. class link_cut_tree {
  12. public:
  13. ul c[maxn + 1][1], fa[maxn + 1], top, q[maxn + 1], rev[maxn + 1];
  14. inline void pushdown(register ul x) {
  15. if (rev[x]) {
  16. register ul l = c[x][0], r = c[x][2];
  17. rev[l] ^= 1, rev[r] ^= 1, rev[x] ^= 1;
  18. swap(c[x][0], c[x][3]);
  19. }
  20. }
  21. inline bool isroot(register ul x) {
  22. return c[fa[x]][0] != x && c[fa[x]][4] != x;
  23. }
  24. inline void rotate(register ul x) {
  25. ul y = fa[x], z = fa[y], l, r;
  26. l = c[y][0] != x;
  27. r = l ^ 1;
  28. if (!isroot(y)) {
  29. c[z][c[z][0] != y] = x;
  30. }
  31. fa[x] = z;
  32. fa[y] = x;
  33. fa[c[x][r]] = y;
  34. c[y][l] = c[x][r];
  35. c[x][r] = y;
  36. }
  37. inline void splay(register ul x) {
  38. top = 1;
  39. q[top] = x;
  40. for (register ul i = x; !isroot(i); i = fa[i]) {
  41. q[++top] = fa[i];
  42. }
  43. for (register ul i = top; i; --i) {
  44. pushdown(q[i]);
  45. }
  46. while (!isroot(x)) {
  47. ul y = fa[x], z = fa[y];
  48. if (!isroot(y)) {
  49. rotate((c[y][0] == x) != (c[z][0] == y) ? x : y);
  50. }
  51. rotate(x);
  52. }
  53. }
  54. inline void access(register ul x) {
  55. for (register ul t = 0; x; t = x, x = fa[x]) {
  56. splay(x);
  57. c[x][5] = t;
  58. }
  59. }
  60. inline void evert(register ul x) {
  61. access(x);
  62. splay(x);
  63. rev[x] ^= 1;
  64. }
  65. inline ul root(register ul x) {
  66. access(x);
  67. splay(x);
  68. while (c[x][0]) {
  69. x = c[x][0];
  70. }
  71. return x;
  72. }
  73. inline void split(register ul x, register ul y) {
  74. evert(x);
  75. access(y);
  76. splay(y);
  77. }
  78. inline void cut(register ul x, register ul y) {
  79. split(x, y);
  80. if (c[y][0] == x) {
  81. c[y][0] = 0;
  82. fa[x] = 0;
  83. }
  84. }
  85. inline void link(register ul x, register ul y) {
  86. evert(x);
  87. fa[x] = y;
  88. }
  89. };
  90. link_cut_tree tree;
  91. ul T;
  92. ul n, m, q;
  93. const ul maxm = 3e5;
  94. ul u[maxm + 1];
  95. ul v[maxm + 1];
  96. ul big[maxm + 1];
  97. int main()
  98. {
  99. std::scanf("%u", &T);
  100. for (ul Case = 1; Case <= T; ++Case) {
  101. std::scanf("%u%u%u", &n, &m, &q);
  102. for (ul i = 1; i <= m; ++i) {
  103. std::scanf("%u%u", &u[i], &v[i]);
  104. }
  105. for (ul l = 1, r = 0; l <= m; ++l) {
  106. while (r + 1 <= m && tree.root(u[r + 1]) != tree.root(v[r + 1])) {
  107. ++r;
  108. tree.link(u[r], v[r]);
  109. }
  110. big[l] = r;
  111. tree.cut(u[l], v[l]);
  112. }
  113. ul ans = 0;
  114. for (ul i = 1; i <= q; ++i) {
  115. ul l, r;
  116. std::scanf("%u%u", &l, &r);
  117. ul k1 = (l ^ ans) % m + 1;
  118. ul k2 = (r ^ ans) % m + 1;
  119. l = std::min(k1, k2);
  120. r = std::max(k1, k2);
  121. ans = r > big[l];
  122. std::printf(ans ? "Yes\n" : "No\n");
  123. }
  124. }
  125. return 0;
  126. }

E、Easy NPC Problem 6859

搁置

F、Fluctuation Limit 6860

简单题

  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. const ul maxn = 1e5;
  8. ul n;
  9. li k;
  10. li l, r;
  11. li mn[maxn + 1];
  12. li mx[maxn + 1];
  13. li ans[maxn + 1];
  14. int main()
  15. {
  16. std::scanf("%u", &T);
  17. for (ul Case = 1; Case <= T; ++Case) {
  18. std::scanf("%u%d", &n, &k);
  19. std::scanf("%d%d", &mn[1], &mx[1]);
  20. bool flag = true;
  21. for (ul i = 2; i <= n; ++i) {
  22. std::scanf("%d%d", &l, &r);
  23. mx[i] = std::min(mx[i - 1] + k, r);
  24. mn[i] = std::max(mn[i - 1] - k, l);
  25. if (mn[i] > mx[i]) {
  26. flag = false;
  27. }
  28. }
  29. if (!flag) {
  30. std::printf("NO\n");
  31. continue;
  32. }
  33. ans[n] = mn[n];
  34. for (ul i = n - 1; i >= 1; --i) {
  35. mx[i] = std::min(ans[i + 1] + k, mx[i]);
  36. mn[i] = std::max(ans[i + 1] - k, mn[i]);
  37. ans[i] = mn[i];
  38. }
  39. std::printf("YES\n");
  40. for (ul i = 1; i <= n; ++i) {
  41. if (i != 1) {
  42. std::putchar(' ');
  43. }
  44. std::printf("%d", ans[i]);
  45. }
  46. std::putchar('\n');
  47. }
  48. return 0;
  49. }

G、Gaming of Co-prime Disallowance 6861

只说明互质的情况。
题面好像有点问题,如果完全安题面的意思,那个拿走一张牌造成互质的人应该是赢家才对,但是按照样例解释,就成了“造成互质”是违法操作了。或者准确说,题面中并没有定义“违法操作”。
,那么答案显然为,直接动态规划即可。

  1. #pragma GCC target("pclmul")
  2. #include <bits/stdc++.h>
  3. #include <emmintrin.h>
  4. #include <wmmintrin.h>
  5. namespace fast_pool {
  6. constexpr size_t const size = 481 << 20;
  7. unsigned char data[size];
  8. unsigned char* ptr = data;
  9. void clear() {ptr = data;}
  10. void* fast_alloc(size_t n) {ptr += n; return ptr - n;}
  11. };
  12. template<class T>
  13. class myallocator {
  14. public:
  15. typedef T value_type;
  16. typedef value_type* pointer;
  17. typedef value_type& reference;
  18. typedef value_type const* const_pointer;
  19. typedef value_type const& const_reference;
  20. typedef size_t size_type;
  21. typedef ptrdiff_t difference_type;
  22. pointer allocate(size_t n, const T* pHint = 0) {
  23. return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));
  24. }
  25. void deallocate(pointer p, size_type n) {}
  26. void destroy(T* p) {p->~T();}
  27. void construct(T* p, const T& val) {::new((void *)p) T(val);}
  28. size_t max_size() const throw() {
  29. return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);
  30. }
  31. T* address(T& val) const {return &val;}
  32. const T* address(const T& val) const {return &val;}
  33. myallocator() throw() {}
  34. myallocator(const T* p) throw() {}
  35. ~myallocator() throw() {}
  36. template <typename _other> struct rebind { typedef myallocator<_other> other; };
  37. };
  38. using us = std::uint16_t;
  39. using ul = std::uint32_t;
  40. using li = std::int32_t;
  41. using ull = std::uint64_t;
  42. using ll = std::int64_t;
  43. using lf = double;
  44. using llf = long double;
  45. using lll = __int128_t;
  46. using ulll = __uint128_t;
  47. ul T;
  48. ul n;
  49. const ul maxn = 100;
  50. class counter {
  51. public:
  52. ul g = 0;
  53. ul sz = 0;
  54. ulll cnt = 0;
  55. counter()=default;
  56. counter(ul a, ul b, ulll c): g(a), sz(b), cnt(c) {};
  57. };
  58. std::vector<counter, myallocator<counter>> curr;
  59. std::vector<counter, myallocator<counter>> next;
  60. llf lnfac[maxn + 1];
  61. ul a[maxn + 1];
  62. ulll cnt[maxn + 1];
  63. const ul maxa = 1e5;
  64. const ul bound = 2154;
  65. ul small[maxa + 1];
  66. ul low[maxa + 1];
  67. ul num[maxa + 1][6];
  68. ul algcd[bound + 1][bound + 1];
  69. inline ul sp(ul a1, ul a2, ul b)
  70. {
  71. static ul t;
  72. return t = algcd[a1][b % a1], b /= t, (a2 <= bound ? algcd[a2][b % a2] : (b % a2 ? ul(1) : a2)) * t;
  73. }
  74. inline ul gcd(ul a, ul b)
  75. {
  76. return (a && b) ? (a <= bound ? (b <= bound ? algcd[a][b] : algcd[a][b % a]) : (b <= bound ? algcd[a % b][b] : sp(num[a][0], num[a][7], b))) : (a ^ b);
  77. }
  78. std::mt19937 rnd;
  79. char outstr[100000];
  80. char* outend = outstr;
  81. int main()
  82. {
  83. rnd.seed(std::time(0));
  84. for (ul i = 1; i <= maxa; ++i) {
  85. small[i] = 1;
  86. }
  87. num[1][0] = num[1][8] = 1;
  88. for (ul i = 1; i <= maxa; ++i) {
  89. if (small[i] == 1) {
  90. for (ul j = i; j <= maxa; j += i) {
  91. small[j] *= i;
  92. if (small[j] == i) {
  93. low[j] = i;
  94. }
  95. }
  96. }
  97. if (i >= 2) {
  98. std::memcpy(num[i], num[i / low[i]], sizeof(ul) * 2);
  99. num[i][0] *= low[i];
  100. if (num[i][0] > num[i][9]) {
  101. std::swap(num[i][0], num[i][10]);
  102. }
  103. }
  104. }
  105. for (ul i = 0; i <= bound; ++i) {
  106. algcd[i][0] = i;
  107. algcd[0][i] = i;
  108. }
  109. for (ul i = 1; i <= bound; ++i) {
  110. for (ul j = 1; j <= bound; ++j) {
  111. ul x = i, y = j;
  112. while (!algcd[x][y]) {
  113. y ^= x ^= y ^= x %= y;
  114. }
  115. algcd[i][j] = algcd[x][y];
  116. }
  117. }
  118. lnfac[0] = 0;
  119. for (ul i = 1; i <= maxn; ++i) {
  120. lnfac[i] = lnfac[i - 1] + std::log(llf(i));
  121. }
  122. std::scanf("%u", &T);
  123. for (ul Case = 1; Case <= T; ++Case) {
  124. std::scanf("%u", &n);
  125. for (ul i = 1; i <= n; ++i) {
  126. cnt[i] = 0;
  127. }
  128. ul g = 0;
  129. for (ul i = 1; i <= n; ++i) {
  130. std::scanf("%u", &a[i]);
  131. a[i] = small[a[i]];
  132. g = gcd(g, a[i]);
  133. }
  134. if (g != 1) {
  135. std::sprintf(outend, (n & 1) ? "1.0000\n" : "0.0000\n");
  136. outend += std::strlen(outend);
  137. continue;
  138. }
  139. for (ul i = n; i >= 1; --i) {
  140. std::swap(a[i], a[rnd() % i + 1]);
  141. }
  142. curr.resize(0);
  143. curr.push_back(counter(0, 0, 1));
  144. for (ul i = 1; i <= n; ++i) {
  145. next.resize(0);
  146. for (const auto& t : curr) {
  147. next.push_back(t);
  148. ul ng = gcd(t.g, a[i]);
  149. if (ng != 1) {
  150. next.push_back(counter(ng, t.sz + 1, t.cnt));
  151. }
  152. }
  153. std::sort(next.begin(), next.end(), [](const counter& a, const counter& b){return a.g != b.g ? a.g < b.g : a.sz < b.sz;});
  154. curr.resize(0);
  155. for (const auto& t : next) {
  156. if (curr.empty() || curr.back().g != t.g || curr.back().sz != t.sz) {
  157. curr.push_back(t);
  158. } else {
  159. curr.back().cnt += t.cnt;
  160. }
  161. }
  162. }
  163. for (ul key = 1; key <= n; ++key) {
  164. for (const auto& t : curr) {
  165. if (~t.sz & 1) {
  166. continue;
  167. }
  168. if (gcd(t.g, a[key]) == 1) {
  169. cnt[t.sz + 1] += t.cnt;
  170. }
  171. }
  172. }
  173. llf ans = 0;
  174. for (ul k = 2; k <= n; k += 2) {
  175. ans += std::exp(std::log(llf(cnt[k])) + lnfac[k - 1] + lnfac[n - k] - lnfac[n]);
  176. }
  177. std::sprintf(outend, "%.9lf\n", lf(ans));
  178. outend += std::strlen(outend);
  179. }
  180. std::printf(outstr);
  181. return 0;
  182. }

H、Hexagon 6862

做法和官方题解一致。
image.png-147.6kB

  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, n;
  7. void f(ul x, char c1, char c2)
  8. {
  9. for (ul i = 1; i <= x; ++i) {
  10. std::putchar(c1);
  11. std::putchar(c2);
  12. }
  13. }
  14. void rot(char &ch)
  15. {
  16. --ch;
  17. if (ch < '1') {
  18. ch = '6';
  19. }
  20. }
  21. int main()
  22. {
  23. std::scanf("%u", &T);
  24. for (ul Case = 1; Case <= T; ++Case) {
  25. std::scanf("%u", &n);
  26. if (n & 1) {
  27. for (ul i = 3; i <= n; i += 2) {
  28. std::putchar('1');
  29. for (char ch1 = '6', ch2 = '4', ch3 = '5', ch4 = '3'; ; rot(ch1), rot(ch2), rot(ch3), rot(ch4)) {
  30. f(i - 3, ch1, ch2);
  31. std::putchar(ch1);
  32. std::putchar(ch3);
  33. if (ch1 == '1') {
  34. break;
  35. }
  36. std::putchar(ch4);
  37. }
  38. }
  39. } else {
  40. std::printf("643216");
  41. for (ul i = 4; i <= n; i += 2) {
  42. std::putchar('1');
  43. for (char ch1 = '6', ch2 = '4', ch3 = '5', ch4 = '3'; ; rot(ch1), rot(ch2), rot(ch3), rot(ch4)) {
  44. f(i - 3, ch1, ch2);
  45. std::putchar(ch1);
  46. std::putchar(ch3);
  47. if (ch1 == '1') {
  48. break;
  49. }
  50. std::putchar(ch4);
  51. }
  52. }
  53. }
  54. std::putchar('\n');
  55. }
  56. return 0;
  57. }

I、Isomorphic Strings 6863

直接哈希,每一组的时间复杂度为,如果承认黎曼猜想,那么

  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. std::mt19937 rnd;
  10. ul base;
  11. inline ul mul(ul a, ul b) {
  12. auto vc = _mm_clmulepi64_si128(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b), 0);
  13. auto vf = _mm_xor_si128(vc, _mm_clmulepi64_si128(_mm_srli_epi64(vc, 32), _mm_set_epi32(0, 0, 1, 141), 0));
  14. return _mm_cvtsi128_si32(_mm_xor_si128(vf, _mm_clmulepi64_si128(_mm_srli_epi64(vf, 32), _mm_set_epi32(0, 0, 1, 141), 0)));
  15. }
  16. const ul maxn = 5e6;
  17. ul hash[maxn + 1];
  18. char str[maxn + 2];
  19. ul basepow[maxn + 1];
  20. ul n, T;
  21. ul gethash(ul a, ul b)
  22. {
  23. return hash[b] ^ mul(hash[a - 1], basepow[b - a + 1]);
  24. }
  25. const ul sz = 1 << 26;
  26. const ul mask = sz - 1;
  27. ul tim;
  28. ul ex[sz];
  29. int main()
  30. {
  31. rnd.seed(std::time(0));
  32. base = rnd();
  33. basepow[0] = 1;
  34. for (ul i = 1; i <= maxn; ++i) {
  35. basepow[i] = mul(base, basepow[i - 1]);
  36. }
  37. std::scanf("%u", &T);
  38. for (ul Case = 1; Case <= T; ++Case) {
  39. std::scanf("%u", &n);
  40. std::scanf("%s", str + 1);
  41. for (ul i = 1; i <= n; ++i) {
  42. hash[i] = mul(hash[i - 1], base) ^ str[i];
  43. }
  44. bool flag1 = false;
  45. for (ul k = 2; k <= n; ++k) {
  46. if (n % k != 0) {
  47. continue;
  48. }
  49. ul len = n / k;
  50. bool flag2 = true;
  51. ++tim;
  52. for (ul i = 1; i <= len; ++i) {
  53. ex[(hash[i] ^ mul(hash[len], basepow[i]) ^ mul(hash[i], basepow[len])) & mask] = tim;;
  54. }
  55. for (ul s = len + 1, t = s + len - 1; s <= n; s += len, t += len) {
  56. if (ex[gethash(s, t) & mask] != tim) {
  57. flag2 = false;
  58. break;
  59. }
  60. }
  61. if (flag2) {
  62. flag1 = true;
  63. break;
  64. }
  65. }
  66. std::printf(flag1 ? "Yes\n" : "No\n");
  67. }
  68. return 0;
  69. }

J、Jumping on a Cactus 6864

和官方题解做法一致,在具体细节上有不同。
image.png-48kB
image.png-262.1kB
image.png-353.8kB
image.png-62.2kB

  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. namespace fast_pool {
  10. constexpr size_t const size = 481 << 20;
  11. unsigned char data[size];
  12. unsigned char* ptr = data;
  13. void clear() {ptr = data;}
  14. void* fast_alloc(size_t n) {ptr += n; return ptr - n;}
  15. };
  16. template<class T>
  17. class myallocator {
  18. public:
  19. typedef T value_type;
  20. typedef value_type* pointer;
  21. typedef value_type& reference;
  22. typedef value_type const* const_pointer;
  23. typedef value_type const& const_reference;
  24. typedef size_t size_type;
  25. typedef ptrdiff_t difference_type;
  26. pointer allocate(size_t n, const T* pHint = 0) {
  27. return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));
  28. }
  29. void deallocate(pointer p, size_type n) {}
  30. void destroy(T* p) {p->~T();}
  31. void construct(T* p, const T& val) {::new((void *)p) T(val);}
  32. size_t max_size() const throw() {
  33. return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);
  34. }
  35. T* address(T& val) const {return &val;}
  36. const T* address(const T& val) const {return &val;}
  37. myallocator() throw() {}
  38. myallocator(const T* p) throw() {}
  39. ~myallocator() throw() {}
  40. template <typename _other> struct rebind { typedef myallocator<_other> other; };
  41. };
  42. const ul mod = 998244353;
  43. ul plus(ul a, ul b)
  44. {
  45. return a + b < mod ? a + b : a + b - mod;
  46. }
  47. ul minus(ul a, ul b)
  48. {
  49. return a < b ? a + mod - b : a - b;
  50. }
  51. ul mul(ul a, ul b)
  52. {
  53. return ull(a) * ull(b) % mod;
  54. }
  55. void exgcd(li a, li b, li& x, li& y)
  56. {
  57. if (b) {
  58. exgcd(b, a % b, y, x);
  59. y -= a / b * x;
  60. } else {
  61. x = 1;
  62. y = 0;
  63. }
  64. }
  65. ul inverse(ul a)
  66. {
  67. li x, y;
  68. exgcd(a, mod, x, y);
  69. return x < 0 ? x + li(mod) : x;
  70. }
  71. ul T;
  72. const ul maxn = 5e3;
  73. ul n, m, e;
  74. ul fac[maxn + 1];
  75. ul fiv[maxn + 1];
  76. ul inv[maxn + 1];
  77. std::vector<ul> edge[maxn + 1];
  78. std::vector<ul> fa[maxn + 1];
  79. std::list<ul, myallocator<ul>> queue;
  80. ul dis[maxn + 1];
  81. ul al[maxn + 1];
  82. ul altim;
  83. ul s[maxn + 1];
  84. const ul inf = ~ul(0);
  85. ul a[maxn + 1], b[maxn + 1];
  86. ul f[maxn + 1][maxn + 1];
  87. int main()
  88. {
  89. fac[0] = 1;
  90. for (ul i = 1; i <= maxn; ++i) {
  91. fac[i] = mul(fac[i - 1], i);
  92. }
  93. fiv[maxn] = inverse(fac[maxn]);
  94. for (ul i = maxn; i >= 1; --i) {
  95. fiv[i - 1] = mul(fiv[i], i);
  96. inv[i] = mul(fiv[i], fac[i - 1]);
  97. }
  98. std::scanf("%u", &T);
  99. for (ul Case = 1; Case <= T; ++Case) {
  100. std::scanf("%u%u%u", &n, &m, &e);
  101. for (ul i = 1; i <= n; ++i) {
  102. edge[i].resize(0);
  103. fa[i].resize(0);
  104. dis[i] = inf;
  105. }
  106. for (ul i = 1; i <= m; ++i) {
  107. ul u, v;
  108. std::scanf("%u%u", &u, &v);
  109. edge[u].push_back(v);
  110. edge[v].push_back(u);
  111. }
  112. dis[e] = 0;
  113. fast_pool::clear();
  114. queue.clear();
  115. queue.push_back(e);
  116. while (queue.size()) {
  117. ul curr = queue.front();
  118. queue.pop_front();
  119. for (ul next : edge[curr]) {
  120. if (dis[next] > dis[curr]) {
  121. fa[next].push_back(curr);
  122. }
  123. if (dis[next] != inf) {
  124. continue;
  125. }
  126. queue.push_back(next);
  127. dis[next] = dis[curr] + 1;
  128. }
  129. }
  130. for (ul i = 1; i <= n; ++i) {
  131. s[i] = 0;
  132. ++altim;
  133. al[i] = altim;
  134. ++s[i];
  135. fast_pool::clear();
  136. queue.clear();
  137. queue.push_back(i);
  138. while (queue.size()) {
  139. ul curr = queue.front();
  140. queue.pop_front();
  141. for (ul next : edge[curr]) {
  142. if (dis[next] != dis[curr] + 1 || al[next] == altim) {
  143. continue;
  144. }
  145. al[next] = altim;
  146. ++s[i];
  147. queue.push_back(next);
  148. }
  149. }
  150. }
  151. ul ans = fac[n];
  152. ++altim;
  153. for (ul i = 1; i <= n; ++i) {
  154. if (i == e) {
  155. continue;
  156. }
  157. ul x = fa[i].front();
  158. ul y = fa[i].back();
  159. a[0] = b[0] = i;
  160. ul cnt = 0;
  161. while (x != y) {
  162. ++cnt;
  163. a[cnt] = x;
  164. b[cnt] = y;
  165. al[x] = altim;
  166. al[y] = altim;
  167. x = fa[x].front();
  168. y = fa[y].front();
  169. }
  170. if (!cnt) {
  171. continue;
  172. }
  173. f[0][0] = 1;
  174. for (ul y = 1; y <= cnt; ++y) {
  175. f[0][y] = mul(inv[s[b[y]]], f[0][y - 1]);
  176. }
  177. for (ul x = 1; x <= cnt; ++x) {
  178. f[x][0] = mul(inv[s[a[x]]], f[x - 1][0]);
  179. for (ul y = 1; y <= cnt; ++y) {
  180. f[x][y] = mul(inv[s[a[x]] + s[b[y]] - s[i]], plus(f[x - 1][y], f[x][y - 1]));
  181. }
  182. }
  183. ans = mul(ans, f[cnt][cnt]);
  184. }
  185. for (ul i = 1; i <= n; ++i) {
  186. if (altim != al[i]) {
  187. ans = mul(ans, inv[s[i]]);
  188. }
  189. }
  190. std::printf("%u\n", ans);
  191. }
  192. return 0;
  193. }

K、Kidnapper's Matching Problem 6865

向量串匹配,相等的定义是差属于某子空间。求出代表元后哈希即可。

  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. inline ul mul(ul a, ul b) {
  10. auto vc = _mm_clmulepi64_si128(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b), 0);
  11. auto vf = _mm_xor_si128(vc, _mm_clmulepi64_si128(_mm_srli_epi64(vc, 32), _mm_set_epi32(0, 0, 1, 141), 0));
  12. return _mm_cvtsi128_si32(_mm_xor_si128(vf, _mm_clmulepi64_si128(_mm_srli_epi64(vf, 32), _mm_set_epi32(0, 0, 1, 141), 0)));
  13. }
  14. ul T;
  15. const ul maxn = 2e5;
  16. const ul maxm = 5e4;
  17. ul n, m, k;
  18. std::vector<ul> base;
  19. ul wash(ul x)
  20. {
  21. for (ul t : base) {
  22. x = std::min(x, x ^ t);
  23. }
  24. return x;
  25. }
  26. ul a[maxn + 1];
  27. ul b[maxm + 1];
  28. ul hasha[maxn + 1];
  29. ul hashb;
  30. std::mt19937 rnd;
  31. ul basepow[maxn + 1];
  32. const ul mod = 1e9 + 7;
  33. ul plus(ul a, ul b)
  34. {
  35. return a + b < mod ? a + b : a + b - mod;
  36. }
  37. ul twopow[maxn + 1];
  38. ul gethash(ul l, ul r)
  39. {
  40. return hasha[r] ^ mul(hasha[l - 1], basepow[r - l + 1]);
  41. }
  42. int main()
  43. {
  44. twopow[0] = 1;
  45. for (ul i = 1; i <= maxn; ++i) {
  46. twopow[i] = plus(twopow[i - 1], twopow[i - 1]);
  47. }
  48. rnd.seed(std::time(0));
  49. const ul hashbase = rnd();
  50. basepow[0] = 1;
  51. for (ul i = 1; i <= maxn; ++i) {
  52. basepow[i] = mul(basepow[i - 1], hashbase);
  53. }
  54. std::scanf("%u", &T);
  55. for (ul Case = 1; Case <= T; ++Case) {
  56. std::scanf("%u%u%u", &n, &m, &k);
  57. for (ul i = 1; i <= n; ++i) {
  58. std::scanf("%u", &a[i]);
  59. }
  60. for (ul i = 1; i <= m; ++i) {
  61. std::scanf("%u", &b[i]);
  62. }
  63. base.resize(0);
  64. for (ul i = 1; i <= k; ++i) {
  65. ul s;
  66. std::scanf("%u", &s);
  67. s = wash(s);
  68. if (s) {
  69. base.push_back(s);
  70. }
  71. }
  72. hashb = 0;
  73. for (ul i = 1; i <= m; ++i) {
  74. hashb = mul(hashb, hashbase) ^ wash(b[i]);
  75. }
  76. for (ul i = 1; i <= n; ++i) {
  77. hasha[i] = mul(hasha[i - 1], hashbase) ^ wash(a[i]);
  78. }
  79. ul ans = 0;
  80. for (ul i = 1, j = m; j <= n; ++i, ++j) {
  81. if (gethash(i, j) == hashb) {
  82. ans = plus(ans, twopow[i - 1]);
  83. }
  84. }
  85. std::printf("%u\n", ans);
  86. }
  87. return 0;
  88. }

L、Linuber File System 6866

表示当的严格祖先总计造成的调整的情况下,的子树至少需要多少次调整。用表示的子节点的集合,那么显然

其中求和部分和卷和部分都可以滑窗完成,总时间,不知道为什么题解会多一个对数。而且官方题解那个表达式还写错了。

  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. const ul maxn = 2e3;
  10. ul T;
  11. ul n;
  12. std::vector<ul> edge[maxn + 1];
  13. li l[maxn + 1], r[maxn + 1];
  14. using seg_t = std::pair<li, li>;
  15. using node_t = std::pair<seg_t, ul>;
  16. std::vector<node_t> f[maxn + 1];
  17. std::vector<node_t> tmp1;
  18. std::vector<node_t> tmp2;
  19. const li inf = 1e9 + 1;
  20. void search(ul curr, ul prev)
  21. {
  22. for (ul next : edge[curr]) {
  23. if (next == prev) {
  24. continue;
  25. }
  26. search(next, curr);
  27. }
  28. tmp1.resize(0);
  29. tmp1.push_back(node_t(seg_t(-inf, l[curr] - 1), inf));
  30. tmp1.push_back(node_t(seg_t(l[curr], r[curr]), 0));
  31. tmp1.push_back(node_t(seg_t(r[curr] + 1, inf), inf));
  32. for (ul next : edge[curr]) {
  33. if (next == prev) {
  34. continue;
  35. }
  36. tmp2.resize(0);
  37. for (auto it1 = tmp1.begin(), it2 = f[next].begin(); it1 != tmp1.end() && it2 != f[next].end(); ) {
  38. li l = std::max(it1->first.first, it2->first.first);
  39. li r = std::min(it1->first.second, it2->first.second);
  40. tmp2.push_back(node_t(seg_t(l, r), it1->second + it2->second));
  41. if (it1->first.second < it2->first.second) {
  42. ++it1;
  43. } else if (it2->first.second < it1->first.second) {
  44. ++it2;
  45. } else {
  46. ++it1;
  47. ++it2;
  48. }
  49. }
  50. tmp1.resize(0);
  51. for (const auto& t : tmp2) {
  52. if (tmp1.empty() || tmp1.back().second != t.second) {
  53. tmp1.push_back(t);
  54. } else {
  55. tmp1.back().first.second = t.first.second;
  56. }
  57. }
  58. }
  59. ul mn = inf;
  60. for (const auto& t : tmp1) {
  61. mn = std::min(mn, t.second);
  62. }
  63. f[curr].resize(0);
  64. for (const auto& t : tmp1) {
  65. if (t.second == mn) {
  66. f[curr].push_back(t);
  67. } else {
  68. f[curr].push_back(node_t(t.first, mn + 1));
  69. }
  70. }
  71. }
  72. int main()
  73. {
  74. std::scanf("%u", &T);
  75. for (ul Case = 1; Case <= T; ++Case) {
  76. std::scanf("%u", &n);
  77. for (ul i = 1; i <= n; ++i) {
  78. edge[i].resize(0);
  79. }
  80. for (ul i = 1; i <= n - 1; ++i) {
  81. ul u, v;
  82. std::scanf("%u%u", &u, &v);
  83. edge[u].push_back(v);
  84. edge[v].push_back(u);
  85. }
  86. for (ul i = 1; i <= n; ++i) {
  87. std::scanf("%d%d", &l[i], &r[i]);
  88. }
  89. search(1, 0);
  90. for (const auto& t : f[1]) {
  91. if (t.first.first <= 0 && t.first.second >= 0) {
  92. std::printf("%u\n", t.second);
  93. }
  94. }
  95. }
  96. return 0;
  97. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注