[关闭]
@qq290637843 2021-03-10T13:44:44.000000Z 字数 20044 阅读 234

2019沈阳

一共有十三道题,其中十道题在此处可以提交https://ac.nowcoder.com/acm/contest/7830
另外三道题的题面可以找我qq联系要题面,这三道题中有两道我有数据,但给我数据的人要求不外传,所以我只能帮忙代运行代码。

A、Leftbest

简单题

  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. std::set<ul> set;
  7. int main()
  8. {
  9. ull ans = 0;
  10. ul n;
  11. std::scanf("%u", &n);
  12. for (ul i = 1; i <= n; ++i) {
  13. ul a;
  14. std::scanf("%u", &a);
  15. auto it = std::next(set.insert(a).first);
  16. if (it != set.end()) {
  17. ans += *it;
  18. }
  19. }
  20. std::printf("%llu\n", ans);
  21. return 0;
  22. }

B、First Date

显然最短路长度关于构成一个凹函数,所以可以根据相邻两个采样点的次导数以及值来判断是否足够接近。

  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 lf = double;
  7. using llf = long double;
  8. ul n, m, s, t;
  9. const ul maxn = 200;
  10. class edge_t {
  11. public:
  12. llf x = 0;
  13. llf y = 0;
  14. ul to = 0;
  15. edge_t()=default;
  16. edge_t(ul a, llf b, llf c): to(a), x(b), y(c) {}
  17. };
  18. class ach_t {
  19. public:
  20. llf dis = 0;
  21. ul to = 0;
  22. ach_t()=default;
  23. ach_t(ul a, llf b): to(a), dis(b) {}
  24. };
  25. bool operator<(const ach_t& a, const ach_t& b)
  26. {
  27. return a.dis > b.dis;
  28. }
  29. std::vector<edge_t> edges[maxn + 1];
  30. const llf inf = 1e15;
  31. void calc(llf a, llf& ans, llf& dans)
  32. {
  33. static llf dis[maxn + 1];
  34. static llf ddis[maxn + 1];
  35. static bool al[maxn + 1];
  36. static std::priority_queue<ach_t> heap;
  37. for (ul i = 1; i <= n; ++i) {
  38. dis[i] = inf;
  39. al[i] = false;
  40. }
  41. dis[s] = 0;
  42. ddis[s] = 0;
  43. heap.push(ach_t(s, 0));
  44. while (heap.size()) {
  45. auto curr = heap.top();
  46. heap.pop();
  47. if (al[curr.to]) {
  48. continue;
  49. }
  50. al[curr.to] = true;
  51. for (const auto& e : edges[curr.to]) {
  52. llf newdis = a * e.y + e.x + curr.dis;
  53. if (newdis < dis[e.to]) {
  54. dis[e.to] = newdis;
  55. ddis[e.to] = ddis[curr.to] + e.y;
  56. heap.push(ach_t(e.to, newdis));
  57. }
  58. }
  59. }
  60. ans = dis[t];
  61. dans = ddis[t];
  62. }
  63. class point {
  64. public:
  65. llf a = 0;
  66. llf dis = 0;
  67. llf ddis = 0;
  68. point()=default;
  69. point(llf x, llf y, llf z): a(x), dis(y), ddis(z) {}
  70. };
  71. std::vector<point> stack;
  72. std::priority_queue<llf, std::vector<llf>, std::greater<llf>> heap;
  73. const llf eps = 1e-4;
  74. int main()
  75. {
  76. std::scanf("%u%u%u%u", &n, &m, &s, &t);
  77. for (ul i = 1; i <= m; ++i) {
  78. ul u, v;
  79. lf x, y;
  80. std::scanf("%u%u%lf%lf", &u, &v, &x, &y);
  81. edges[u].push_back(edge_t(v, x, y));
  82. edges[v].push_back(edge_t(u, x, y));
  83. }
  84. llf tans, tdans;
  85. calc(0, tans, tdans);
  86. stack.push_back(point(0, tans, tdans));
  87. calc(1, tans, tdans);
  88. stack.push_back(point(1, tans, tdans));
  89. while (stack.size() >= 2) {
  90. auto p2 = stack.back();
  91. llf d2 = p2.ddis;
  92. llf y2 = p2.dis;
  93. llf x2 = p2.a;
  94. stack.pop_back();
  95. auto p1 = stack.back();
  96. llf d1 = p1.ddis;
  97. llf y1 = p1.dis;
  98. llf x1 = p1.a;
  99. if (ll(d2) == ll(d1)) {
  100. heap.push((y1 + y2) * (x2 - x1) * llf(0.5));
  101. continue;
  102. }
  103. point p3;
  104. llf kk = x2 - x1;
  105. llf sp = -(-d1 * kk + (y2 - y1)) * (-d2 * kk + (y2 - y1)) / (d1 - d2) / kk;
  106. if (sp <= eps) {
  107. heap.push((y1 + y2) * (x2 - x1) * llf(0.5));
  108. continue;
  109. }
  110. p3.a = ((y2 - y1) + (x1 * d1 - x2 * d2)) / (d1 - d2);
  111. calc(p3.a, p3.dis, p3.ddis);
  112. stack.push_back(p3);
  113. stack.push_back(p2);
  114. }
  115. while (heap.size() >= 2) {
  116. auto a = heap.top();
  117. heap.pop();
  118. auto b = heap.top();
  119. heap.pop();
  120. heap.push(a + b);
  121. }
  122. std::printf("%.6lf\n", lf(heap.top()));
  123. return 0;
  124. }

C、Sequence

第一个表达式的来源会用到https://chaoli.club/index.php/5490/
对于第个位置,使其好的数列数量为:

故所有好的(数列,位置)对的数量为
其中
可以直接多项式求商得出,将此记为,于是原式变为
这显然是一次卷积就能完成的。

  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 n, L;
  8. const ul maxn = 1e5;
  9. const ul base = 998244353;
  10. const ul& mod = base;
  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] = minus(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. class ntt_t {
  89. public:
  90. static const ul lgsz = 20;
  91. static const ul sz = 1 << lgsz;
  92. static const ul g = 3;
  93. ul w[sz + 1];
  94. ul leninv[lgsz + 1];
  95. ntt_t() {
  96. ul wn = pow(g, (base - 1) >> lgsz);
  97. w[0] = 1;
  98. for (ul i = 1; i <= sz; ++i) {
  99. w[i] = mul(w[i - 1], wn);
  100. }
  101. leninv[lgsz] = inverse(sz);
  102. for (ul i = lgsz - 1; ~i; --i) {
  103. leninv[i] = plus(leninv[i + 1], leninv[i + 1]);
  104. }
  105. }
  106. void operator()(vul& v, ul& n, bool inv) {
  107. ul lgn = 0;
  108. while ((1 << lgn) < n) {
  109. ++lgn;
  110. }
  111. n = 1 << lgn;
  112. v.resize(n, 0);
  113. for (ul i = 0, j = 0; i != n; ++i) {
  114. if (i < j) {
  115. std::swap(v[i], v[j]);
  116. }
  117. ul k = n >> 1;
  118. while (k & j) {
  119. j &= ~k;
  120. k >>= 1;
  121. }
  122. j |= k;
  123. }
  124. for (ul lgmid = 0; (1 << lgmid) != n; ++lgmid) {
  125. ul mid = 1 << lgmid;
  126. ul len = mid << 1;
  127. for (ul i = 0; i != n; i += len) {
  128. for (ul j = 0; j != mid; ++j) {
  129. ul t0 = v[i + j];
  130. ul t1 = mul(w[inv ? (len - j << lgsz - lgmid - 1) : (j << lgsz - lgmid - 1)], v[i + j + mid]);
  131. v[i + j] = plus(t0, t1);
  132. v[i + j + mid] = minus(t0, t1);
  133. }
  134. }
  135. }
  136. if (inv) {
  137. for (ul i = 0; i != n; ++i) {
  138. v[i] = mul(v[i], leninv[lgn]);
  139. }
  140. }
  141. }
  142. } ntt;
  143. polynomial& operator*=(polynomial& a, const polynomial& b)
  144. {
  145. if (!b.size() || !a.size()) {
  146. a.resize(0);
  147. return a;
  148. }
  149. polynomial temp = b;
  150. ul npmp1 = a.size() + b.size() - 1;
  151. if (ull(a.size()) * ull(b.size()) <= ull(npmp1) * ull(50)) {
  152. temp.resize(0);
  153. temp.resize(npmp1, 0);
  154. for (ul i = 0; i != a.size(); ++i) {
  155. for (ul j = 0; j != b.size(); ++j) {
  156. temp[i + j] = plus(temp[i + j], mul(a[i], b[j]));
  157. }
  158. }
  159. a = temp;
  160. a.clearzero();
  161. return a;
  162. }
  163. ntt(a, npmp1, false);
  164. ntt(temp, npmp1, false);
  165. for (ul i = 0; i != npmp1; ++i) {
  166. a[i] = mul(a[i], temp[i]);
  167. }
  168. ntt(a, npmp1, true);
  169. a.clearzero();
  170. return a;
  171. }
  172. polynomial operator*(const polynomial& a, const polynomial& b)
  173. {
  174. polynomial ret = a;
  175. return ret *= b;
  176. }
  177. polynomial& operator*=(polynomial& a, ul b)
  178. {
  179. if (!b) {
  180. a.resize(0);
  181. return a;
  182. }
  183. for (ul i = 0; i != a.size(); ++i) {
  184. a[i] = mul(a[i], b);
  185. }
  186. return a;
  187. }
  188. polynomial operator*(const polynomial& a, ul b)
  189. {
  190. polynomial ret = a;
  191. return ret *= b;
  192. }
  193. polynomial inverse(const polynomial& a, ul lgdeg)
  194. {
  195. polynomial ret({inverse(a[0])});
  196. polynomial temp;
  197. polynomial tempa;
  198. for (ul i = 0; i != lgdeg; ++i) {
  199. tempa.resize(0);
  200. tempa.resize(1 << i << 1, 0);
  201. for (ul j = 0; j != tempa.size() && j != a.size(); ++j) {
  202. tempa[j] = a[j];
  203. }
  204. temp = ret * (polynomial({2}) - tempa * ret);
  205. if (temp.size() > (1 << i << 1)) {
  206. temp.resize(1 << i << 1, 0);
  207. }
  208. temp.clearzero();
  209. std::swap(temp, ret);
  210. }
  211. return ret;
  212. }
  213. ul fac[maxn + 1];
  214. ul fiv[maxn + 1];
  215. polynomial p1, p2, p3;
  216. ul binomial(ul a, ul b)
  217. {
  218. return mul(fac[a], mul(fiv[b], fiv[a - b]));
  219. }
  220. int main()
  221. {
  222. std::scanf("%u%u", &n, &L);
  223. L %= mod;
  224. fac[0] = 1;
  225. for (ul i = 1; i <= n; ++i) {
  226. fac[i] = mul(fac[i - 1], i);
  227. }
  228. fiv[n] = inverse(fac[n]);
  229. for (ul i = n; i; --i) {
  230. fiv[i - 1] = mul(fiv[i], i);
  231. }
  232. p1.resize(n);
  233. p2.resize(n);
  234. for (ul i = 1, Li = L; i <= n; ++i, Li = mul(Li, L)) {
  235. p1[i - 1] = mul(Li, fiv[i]);
  236. p2[i - 1] = fiv[i];
  237. }
  238. p2 = inverse(p2, 32 - __builtin_clz(n - 1));
  239. p2.resize(n);
  240. p3 = p1 * p2;
  241. p3.resize(n);
  242. p1.resize(n);
  243. p2.resize(n);
  244. for (ul r = n - 1, Lnm1mr = 1; r >= 1; --r, Lnm1mr = mul(Lnm1mr, L)) {
  245. p1[r] = mul(mul(mul(mul(p3[r], fac[r]), binomial(n, r + 1)), Lnm1mr), fac[r - 1]);
  246. if (r & 1) {
  247. p1[r] = minus(0, p1[r]);
  248. }
  249. p2[r] = fiv[r];
  250. }
  251. p2[0] = fiv[0];
  252. std::reverse(p1.begin(), p1.end());
  253. p3 = p1 * p2;
  254. p3.resize(n);
  255. std::reverse(p3.begin(), p3.end());
  256. for (ul k = 1; k <= n - 1; ++k) {
  257. p3[k] = mul(p3[k], fiv[k - 1]);
  258. if (k & 1) {
  259. p3[k] = minus(0, p3[k]);
  260. }
  261. std::printf("%u ", p3[k]);
  262. }
  263. std::printf("0\n");
  264. return 0;
  265. }

D、Quickpow

简单题

  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 llf = long double;
  7. ul n;
  8. const ul maxn = 1e5;
  9. ul a[maxn + 1];
  10. ul mn = 1e9;
  11. ul cnt[11];
  12. int main()
  13. {
  14. std::scanf("%u", &n);
  15. for (ul i = 1; i <= n; ++i) {
  16. std::scanf("%u", &a[i]);
  17. mn = std::min(mn, a[i]);
  18. }
  19. for (ul i = 1; i <= n; ++i) {
  20. a[i] -= mn;
  21. ++cnt[a[i]];
  22. }
  23. llf sum = 0;
  24. for (ul i = 10; ~i; --i) {
  25. sum = sum * std::exp(llf(1));
  26. sum += llf(cnt[i]);
  27. }
  28. for (ul i = 1; i <= n; ++i) {
  29. if (i != 1) {
  30. std::putchar(' ');
  31. }
  32. std::printf("%.8lf", std::exp(llf(a[i])) / sum);
  33. }
  34. std::putchar('\n');
  35. return 0;
  36. }

E、Capture Stars

虚线圆的圆心称为,小圆圆心称为,大圆圆心称为,于是

故构成一个椭圆,其以为焦点。现以为极心建立极坐标系,以为零度方向。于是该椭圆的方程为
现在考虑两点的距离,显然此二点的距离为
于是点所对应的圆能框住某点当且仅当:
借助万能公式并将记为,上式改为:
解二次方程即可。

  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 llf = long double;
  7. using lf = double;
  8. ul T;
  9. ul n;
  10. const ul maxn = 1e4;
  11. llf R, r;
  12. llf in()
  13. {
  14. lf tmp;
  15. std::scanf("%lf", &tmp);
  16. return tmp;
  17. }
  18. void calc(llf a, llf b, llf c, llf& ans1, llf& ans2)
  19. {
  20. llf delta = std::max(b * b - llf(4) * a * c, llf(0));
  21. ans1 = (-b - std::sqrt(delta)) / (a + a);
  22. ans2 = (-b + std::sqrt(delta)) / (a + a);
  23. }
  24. ul tot;
  25. std::pair<llf, char> v[maxn + maxn + 1];
  26. int main()
  27. {
  28. std::scanf("%u", &T);
  29. for (ul Case = 1; Case <= T; ++Case) {
  30. std::scanf("%u", &n);
  31. R = in();
  32. r = in();
  33. tot = 0;
  34. for (ul i = 1; i <= n; ++i) {
  35. llf x = in();
  36. llf y = in();
  37. llf rhos = std::sqrt((x - r) * (x - r) + y * y);
  38. llf costhetas = (x - r) / rhos;
  39. llf sinthetas = y / rhos;
  40. llf t1, t2;
  41. calc(r * r * R + R * rhos * rhos + 2 * r * R * rhos * costhetas, -4 * r * R * rhos * sinthetas, -r * r * r + 2 * r * r * R + r * rhos * rhos - 2 * r * R * rhos * costhetas, t1, t2);
  42. if (t1 > t2) {
  43. std::swap(t1, t2);
  44. }
  45. ++tot;
  46. v[tot].first = t1;
  47. v[tot].second = '(';
  48. ++tot;
  49. v[tot].first = t2;
  50. v[tot].second = ')';
  51. }
  52. std::sort(v + 1, v + n + n + 1);
  53. ul mx = 0;
  54. ul cnt = 0;
  55. for (ul i = 1; i <= n + n; ++i) {
  56. if (v[i].second == '(') {
  57. ++cnt;
  58. mx = std::max(mx, cnt);
  59. } else if (v[i].second == ')') {
  60. --cnt;
  61. }
  62. }
  63. std::printf("%u\n", mx);
  64. }
  65. return 0;
  66. }

F、Crossroads

没有数据,搁置

G、Triangulation

简单题

  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 llf = long double;
  7. using lf = double;
  8. ul n;
  9. const ul maxn = 200;
  10. ll x[maxn + 1];
  11. ll y[maxn + 1];
  12. bool already[maxn + 1][maxn + 1];
  13. ul ans[maxn + 1][maxn + 1];
  14. const ul mod = 998244353;
  15. ul plus(ul a, ul b)
  16. {
  17. return a + b < mod ? a + b : a + b - mod;
  18. }
  19. ul mul(ul a, ul b)
  20. {
  21. return ull(a) * ull(b) % mod;
  22. }
  23. ul calc(ul l, ul r)
  24. {
  25. if (already[l][r]) {
  26. return ans[l][r];
  27. }
  28. already[l][r] = true;
  29. if (l + 1 == r) {
  30. return ans[l][r] = 1;
  31. }
  32. for (ul m = l + 1; m + 1 <= r; ++m) {
  33. if ((x[r] - x[m]) * (y[l] - y[m]) - (x[l] - x[m]) * (y[r] - y[m]) > 0) {
  34. ans[l][r] = plus(ans[l][r], mul(calc(l, m), calc(m, r)));
  35. }
  36. }
  37. return ans[l][r];
  38. }
  39. int main()
  40. {
  41. std::scanf("%u", &n);
  42. ll sum = 0;
  43. for (ul i = 1; i <= n; ++i) {
  44. std::scanf("%lld%lld", &x[i], &y[i]);
  45. if (i != 1) {
  46. sum += x[i - 1] * y[i] - x[i] * y[i - 1];
  47. }
  48. }
  49. sum += x[n] * y[1] - x[1] * y[n];
  50. if (sum < 0) {
  51. std::reverse(x + 1, x + n + 1);
  52. std::reverse(y + 1, y + n + 1);
  53. }
  54. std::printf("%u\n", calc(1, n));
  55. return 0;
  56. }

H、Points

简单题

  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 ul maxn = 2e5;
  8. ul d[maxn + 1];
  9. ul cnt = 0;
  10. int main()
  11. {
  12. std::scanf("%u", &n);
  13. for (ul i = 1; i <= n - 1; ++i) {
  14. ul a, b;
  15. std::scanf("%u%u", &a, &b);
  16. ++d[a];
  17. ++d[b];
  18. }
  19. for (ul i = 1; i <= n; ++i) {
  20. if (d[i] == 1) {
  21. ++cnt;
  22. }
  23. }
  24. std::printf("%u\n", cnt);
  25. return 0;
  26. }

I、Parallel Network Analysis

一个排列如果满足以下二条件之一,则称其为双调排列:
1、升降升,且首项大于等于尾项;
2、降升降,且首项小于等于尾项。
注意,升降、降升、升、降序列都复合以上要求。
现在考虑有一长为的双调序列,那么简单分类讨论可证(为了符合直观印象,建议画图),都是长为的双调序列,且第一个序列的最大值小于等于第二个序列的最小值。由此可知,如果一个长为的序列一开始是双调的,那么只要经过次这样的合并过程就变成升序列了。
现在假设有一长的序列,其中前已经是升序,后已经是升序,那么显然都是长为的双调序列(第一个显然是升降序列,第二个显然是降升序列,建议画图一眼看出),且第一个序列的最大值小于等于第二个序列的最小值,接着再使用上一段的结论可以得到长为的升序列。

  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. std::vector<std::pair<ul, ul>> a[106];
  8. void bisort(ul l, ul r, ul tot)
  9. {
  10. if (l + 1 == r) {
  11. return;
  12. }
  13. ++tot;
  14. for (ul i = l, j = r + l >> 1; j != r; ++i, ++j) {
  15. if (j < n) {
  16. a[tot].push_back(std::pair<ul, ul>(i, j));
  17. }
  18. }
  19. bisort(l, l + r >> 1, tot);
  20. bisort(l + r >> 1, r, tot);
  21. }
  22. void sort(ul l, ul r, ul tot)
  23. {
  24. if (l + 1 == r) {
  25. return;
  26. }
  27. sort(l, l + r >> 1, tot - __builtin_ctz(r - l));
  28. sort(l + r >> 1, r, tot - __builtin_ctz(r - l));
  29. tot -= __builtin_ctz(r - l);
  30. ++tot;
  31. for (ul i = l, j = r - 1; i < j; ++i, --j) {
  32. if (j < n) {
  33. a[tot].push_back(std::pair<ul, ul>(i, j));
  34. }
  35. }
  36. bisort(l, l + r >> 1, tot);
  37. bisort(l + r >> 1, r, tot);
  38. }
  39. int main()
  40. {
  41. std::scanf("%u", &n);
  42. ul tot = 0;
  43. ul k = 32 - __builtin_clz(n - 1);
  44. if (n == 1 || n == 0) {
  45. k = 0;
  46. }
  47. for (ul i = 1; i <= k; ++i) {
  48. tot += i;
  49. }
  50. sort(0, 1 << k, tot);
  51. std::printf("%u\n", tot);
  52. for (ul i = 1; i <= tot; ++i) {
  53. std::printf("%u\n", ul(a[i].size()));
  54. for (auto p : a[i]) {
  55. std::printf("%u %u\n", p.first, p.second);
  56. }
  57. }
  58. return 0;
  59. }

J、Graph

根据一号操作的要求可知,图任何时刻都是一个森林,故考虑用割连树维护。关于查询,考虑给每个需要的点对定义一个随机数,分别给所属的树异或上该,于是所有点对都连通当且仅当每棵树的异或值都是

  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. inline void swap(ul& a, ul& b)
  8. {
  9. a ^= b ^= a ^= b;
  10. }
  11. class link_cut_tree {
  12. public:
  13. ul c[maxn + 1][2], fa[maxn + 1], top, q[maxn + 1], rev[maxn + 1];
  14. ull sum[maxn + 1];
  15. ul cnt;
  16. inline void init(ul n) {
  17. for (ul i = 1; i <= n; ++i) {
  18. c[i][0] = c[i][1] = fa[i] = rev[i] = sum[i] = 0;
  19. }
  20. cnt = 0;
  21. }
  22. inline void cfa(ul x, ul y) {
  23. if (fa[x]) {
  24. sum[fa[x]] ^= sum[x];
  25. }
  26. fa[x] = y;
  27. if (fa[x]) {
  28. sum[fa[x]] ^= sum[x];
  29. }
  30. }
  31. inline void pushdown(ul x) {
  32. if (rev[x]) {
  33. ul l = c[x][0], r = c[x][1];
  34. rev[l] ^= 1, rev[r] ^= 1, rev[x] ^= 1;
  35. swap(c[x][0], c[x][1]);
  36. }
  37. }
  38. inline bool isroot(ul x) {
  39. return c[fa[x]][0] != x && c[fa[x]][1] != x;
  40. }
  41. inline void rotate(ul x) {
  42. ul y = fa[x], z = fa[y], l, r;
  43. l = c[y][0] != x;
  44. r = l ^ 1;
  45. if (!isroot(y)) {
  46. c[z][c[z][0] != y] = x;
  47. }
  48. ull tmp1 = sum[x] ^ sum[c[x][r]];
  49. ull tmp2 = sum[y] ^ sum[x];
  50. sum[y] ^= tmp1;
  51. sum[x] ^= tmp2;
  52. fa[x] = z;
  53. fa[y] = x;
  54. fa[c[x][r]] = y;
  55. c[y][l] = c[x][r];
  56. c[x][r] = y;
  57. }
  58. inline void splay(ul x) {
  59. top = 1;
  60. q[top] = x;
  61. for (ul i = x; !isroot(i); i = fa[i]) {
  62. q[++top] = fa[i];
  63. }
  64. for (ul i = top; i; --i) {
  65. pushdown(q[i]);
  66. }
  67. while (!isroot(x)) {
  68. ul y = fa[x], z = fa[y];
  69. if (!isroot(y)) {
  70. rotate((c[y][0] == x) != (c[z][0] == y) ? x : y);
  71. }
  72. rotate(x);
  73. }
  74. }
  75. inline void access(ul x) {
  76. ul xx = x;
  77. for (ul t = 0; x; t = x, x = fa[x]) {
  78. splay(x);
  79. c[x][1] = t;
  80. }
  81. splay(xx);
  82. }
  83. inline void evert(ul x) {
  84. access(x);
  85. rev[x] ^= 1;
  86. }
  87. inline void cut(ul x, ul y) {
  88. evert(x);
  89. if (sum[x]) {
  90. --cnt;
  91. }
  92. access(y);
  93. c[y][0] = 0;
  94. cfa(x, 0);
  95. access(x);
  96. if (sum[x]) {
  97. ++cnt;
  98. }
  99. access(y);
  100. if (sum[y]) {
  101. ++cnt;
  102. }
  103. }
  104. inline void link(ul x, ul y) {
  105. evert(x);
  106. if (sum[x]) {
  107. --cnt;
  108. }
  109. access(y);
  110. if (sum[y]) {
  111. --cnt;
  112. }
  113. cfa(x, y);
  114. if (sum[y]) {
  115. ++cnt;
  116. }
  117. }
  118. inline void change(ul x, ull v) {
  119. access(x);
  120. if (sum[x]) {
  121. --cnt;
  122. }
  123. sum[x] ^= v;
  124. if (sum[x]) {
  125. ++cnt;
  126. }
  127. }
  128. };
  129. link_cut_tree tree;
  130. ul T;
  131. ul n, q;
  132. std::map<ull, ull> w;
  133. std::mt19937_64 rnd;
  134. int main()
  135. {
  136. rnd.seed(std::time(0));
  137. std::scanf("%u", &T);
  138. for (ul Case = 1; Case <= T; ++Case) {
  139. std::scanf("%u%u", &n, &q);
  140. tree.init(n);
  141. for (ul i = 1; i <= q; ++i) {
  142. ul Type;
  143. std::scanf("%u", &Type);
  144. if (Type != 5) {
  145. ul u, v;
  146. std::scanf("%u%u", &u, &v);
  147. if (Type == 1) {
  148. tree.link(u, v);
  149. } else if (Type == 2) {
  150. tree.cut(u, v);
  151. } else if (Type == 3) {
  152. ull t = w[ull(u) << 32 | v] = rnd();
  153. tree.change(u, t);
  154. tree.change(v, t);
  155. } else if (Type == 4) {
  156. ull t = w[ull(u) << 32 | v];
  157. tree.change(u, t);
  158. tree.change(v, t);
  159. }
  160. } else {
  161. std::printf(tree.cnt ? "NO\n" : "YES\n");
  162. }
  163. }
  164. }
  165. return 0;
  166. }

K、Rooted 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. using vul = std::vector<ul>;
  7. ul n;
  8. const ul base = 998244353;
  9. ul plus(ul a, ul b)
  10. {
  11. return a + b < base ? a + b : a + b - base;
  12. }
  13. ul minus(ul a, ul b)
  14. {
  15. return a < b ? a + base - b : a - b;
  16. }
  17. ul mul(ul a, ul b)
  18. {
  19. return ull(a) * ull(b) % base;
  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 -= x * (a / b);
  26. } else {
  27. x = 1;
  28. y = 0;
  29. }
  30. }
  31. ul inverse(ul a)
  32. {
  33. li x, y;
  34. exgcd(a, base, x, y);
  35. return x < 0 ? x + li(base) : x;
  36. }
  37. ul pow(ul a, ul b)
  38. {
  39. ul ret = 1;
  40. ul temp = a;
  41. while (b) {
  42. if (b & 1) {
  43. ret = mul(ret, temp);
  44. }
  45. temp = mul(temp, temp);
  46. b >>= 1;
  47. }
  48. return ret;
  49. }
  50. class polynomial : public vul {
  51. public:
  52. void clearzero() {
  53. while (size() && !back()) {
  54. pop_back();
  55. }
  56. }
  57. polynomial()=default;
  58. polynomial(const vul& a): vul(a) { }
  59. polynomial(vul&& a): vul(std::move(a)) { }
  60. ul degree() const {
  61. return size() - 1;
  62. }
  63. ul operator()(ul x) const {
  64. ul ret = 0;
  65. for (ul i = size() - 1; ~i; --i) {
  66. ret = mul(ret, x);
  67. ret = plus(ret, vul::operator[](i));
  68. }
  69. return ret;
  70. }
  71. };
  72. polynomial& operator+=(polynomial& a, const polynomial& b)
  73. {
  74. a.resize(std::max(a.size(), b.size()), 0);
  75. for (ul i = 0; i != b.size(); ++i) {
  76. a[i] = plus(a[i], b[i]);
  77. }
  78. a.clearzero();
  79. return a;
  80. }
  81. polynomial operator+(const polynomial& a, const polynomial& b)
  82. {
  83. polynomial ret = a;
  84. return ret += b;
  85. }
  86. polynomial& operator-=(polynomial& a, const polynomial& b)
  87. {
  88. a.resize(std::max(a.size(), b.size()), 0);
  89. for (ul i = 0; i != b.size(); ++i) {
  90. a[i] = minus(a[i], b[i]);
  91. }
  92. a.clearzero();
  93. return a;
  94. }
  95. polynomial operator-(const polynomial& a, const polynomial& b)
  96. {
  97. polynomial ret = a;
  98. return ret -= b;
  99. }
  100. class ntt_t {
  101. public:
  102. static const ul lgsz = 20;
  103. static const ul sz = 1 << lgsz;
  104. static const ul g = 3;
  105. ul w[sz + 1];
  106. ul leninv[lgsz + 1];
  107. ntt_t() {
  108. ul wn = pow(g, (base - 1) >> lgsz);
  109. w[0] = 1;
  110. for (ul i = 1; i <= sz; ++i) {
  111. w[i] = mul(w[i - 1], wn);
  112. }
  113. leninv[lgsz] = inverse(sz);
  114. for (ul i = lgsz - 1; ~i; --i) {
  115. leninv[i] = plus(leninv[i + 1], leninv[i + 1]);
  116. }
  117. }
  118. void operator()(vul& v, ul& n, bool inv) {
  119. ul lgn = 0;
  120. while ((1 << lgn) < n) {
  121. ++lgn;
  122. }
  123. n = 1 << lgn;
  124. v.resize(n, 0);
  125. for (ul i = 0, j = 0; i != n; ++i) {
  126. if (i < j) {
  127. std::swap(v[i], v[j]);
  128. }
  129. ul k = n >> 1;
  130. while (k & j) {
  131. j &= ~k;
  132. k >>= 1;
  133. }
  134. j |= k;
  135. }
  136. for (ul lgmid = 0; (1 << lgmid) != n; ++lgmid) {
  137. ul mid = 1 << lgmid;
  138. ul len = mid << 1;
  139. for (ul i = 0; i != n; i += len) {
  140. for (ul j = 0; j != mid; ++j) {
  141. ul t0 = v[i + j];
  142. ul t1 = mul(w[inv ? (len - j << lgsz - lgmid - 1) : (j << lgsz - lgmid - 1)], v[i + j + mid]);
  143. v[i + j] = plus(t0, t1);
  144. v[i + j + mid] = minus(t0, t1);
  145. }
  146. }
  147. }
  148. if (inv) {
  149. for (ul i = 0; i != n; ++i) {
  150. v[i] = mul(v[i], leninv[lgn]);
  151. }
  152. }
  153. }
  154. } ntt;
  155. polynomial& operator*=(polynomial& a, const polynomial& b)
  156. {
  157. if (!b.size() || !a.size()) {
  158. a.resize(0);
  159. return a;
  160. }
  161. polynomial temp = b;
  162. ul npmp1 = a.size() + b.size() - 1;
  163. if (ull(a.size()) * ull(b.size()) <= ull(npmp1) * ull(50)) {
  164. temp.resize(0);
  165. temp.resize(npmp1, 0);
  166. for (ul i = 0; i != a.size(); ++i) {
  167. for (ul j = 0; j != b.size(); ++j) {
  168. temp[i + j] = plus(temp[i + j], mul(a[i], b[j]));
  169. }
  170. }
  171. a = temp;
  172. a.clearzero();
  173. return a;
  174. }
  175. ntt(a, npmp1, false);
  176. ntt(temp, npmp1, false);
  177. for (ul i = 0; i != npmp1; ++i) {
  178. a[i] = mul(a[i], temp[i]);
  179. }
  180. ntt(a, npmp1, true);
  181. a.clearzero();
  182. return a;
  183. }
  184. polynomial operator*(const polynomial& a, const polynomial& b)
  185. {
  186. polynomial ret = a;
  187. return ret *= b;
  188. }
  189. polynomial& operator*=(polynomial& a, ul b)
  190. {
  191. if (!b) {
  192. a.resize(0);
  193. return a;
  194. }
  195. for (ul i = 0; i != a.size(); ++i) {
  196. a[i] = mul(a[i], b);
  197. }
  198. return a;
  199. }
  200. polynomial operator*(const polynomial& a, ul b)
  201. {
  202. polynomial ret = a;
  203. return ret *= b;
  204. }
  205. polynomial inverse(const polynomial& a, ul lgdeg)
  206. {
  207. polynomial ret({inverse(a[0])});
  208. polynomial temp;
  209. polynomial tempa;
  210. for (ul i = 0; i != lgdeg; ++i) {
  211. tempa.resize(0);
  212. tempa.resize(1 << i << 1, 0);
  213. for (ul j = 0; j != tempa.size() && j != a.size(); ++j) {
  214. tempa[j] = a[j];
  215. }
  216. temp = ret * (polynomial({2}) - tempa * ret);
  217. if (temp.size() > (1 << i << 1)) {
  218. temp.resize(1 << i << 1, 0);
  219. }
  220. temp.clearzero();
  221. std::swap(temp, ret);
  222. }
  223. return ret;
  224. }
  225. polynomial v;
  226. int main()
  227. {
  228. std::scanf("%u", &n);
  229. v.resize(n);
  230. v[0] = 1;
  231. for (ul k = 1; k * (3 * k - 1) <= 2 * (n - 1); ++k) {
  232. ul t;
  233. t = (k & 1) ? minus(0, 1) : ul(1);
  234. if (k * (3 * k + 1) / 2 <= n - 1) {
  235. v[k * (3 * k + 1) >> 1] = t;
  236. }
  237. v[k * (3 * k - 1) >> 1] = t;
  238. }
  239. v = inverse(v, n - 1 ? ul(32 - __builtin_clz(n - 1)) : ul(0));
  240. v.resize(n);
  241. std::printf("%u\n", v[n - 1]);
  242. return 0;
  243. }

L、Flowers

二分贪心

  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, m;
  7. const ul maxn = 300000;
  8. ul T;
  9. ul a[maxn + 1];
  10. int main()
  11. {
  12. std::scanf("%u", &T);
  13. for (ul Case = 1; Case <= T; ++Case) {
  14. std::scanf("%u%u", &n, &m);
  15. for (ul i = 1; i <= n; ++i) {
  16. std::scanf("%u", &a[i]);
  17. }
  18. ull l = 0, r = ull(1e9) * ull(n) / ull(m) + 1;
  19. while (l + 1 != r) {
  20. ull mid = l + r >> 1;
  21. ul Q = 0;
  22. ull R = 0;
  23. for (ul i = 1; i <= n; ++i) {
  24. if (a[i] >= mid) {
  25. ++Q;
  26. } else {
  27. R += a[i];
  28. if (R >= mid) {
  29. R -= mid;
  30. ++Q;
  31. }
  32. }
  33. }
  34. if (Q >= m) {
  35. l = mid;
  36. } else {
  37. r = mid;
  38. }
  39. }
  40. std::printf("%llu\n", l);
  41. }
  42. return 0;
  43. }

M、Interesting Strings

出题人给的数据过了,但是不知道是不是强化之后的数据。

  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 uss = std::uint8_t;
  7. const ul maxlen = 2e5;
  8. ul T;
  9. class pam_t {
  10. public:
  11. ul las;
  12. class node {
  13. public:
  14. ul ch[26];
  15. ul len = 0;
  16. ul fa = 0;
  17. ul anc = 0;
  18. node()=default;
  19. node(ul a, ul b): len(a), fa(b) {
  20. std::memset(ch, 0, sizeof(ch));
  21. }
  22. };
  23. std::vector<node> st = std::vector<node>(maxlen + 2);
  24. std::vector<uss> str = std::vector<uss>(maxlen + 1);
  25. ul newnode(ul len, ul fail = 0) {
  26. st.push_back(node(len, fail));
  27. return st.size() - 1;
  28. }
  29. ul getfail(ul x, ul n) {
  30. while (str[n - st[x].len - 1] != str[n]) {
  31. x = st[x].fa;
  32. }
  33. return x;
  34. }
  35. bool add(ul c) {
  36. ul i = str.size();
  37. str.push_back(c);
  38. ul cur = getfail(las, i);
  39. bool flag = false;
  40. if (!st[cur].ch[c]) {
  41. ul nw = newnode(st[cur].len + 2, st[getfail(st[cur].fa, i)].ch[c]);
  42. st[cur].ch[c] = nw;
  43. st[nw].anc = st[nw].len - st[st[nw].fa].len != st[st[nw].fa].len - st[st[st[nw].fa].fa].len ? st[nw].fa : st[st[nw].fa].anc;
  44. flag = true;
  45. }
  46. las = st[cur].ch[c];
  47. return flag;
  48. }
  49. void init() {
  50. str.resize(0);
  51. str.resize(1, 26);
  52. st.resize(0);
  53. newnode(0, 1);
  54. st[1].anc = 0;
  55. newnode(-1, 0);
  56. las = 0;
  57. }
  58. };
  59. pam_t pam;
  60. char str[maxlen + 2];
  61. li f[maxlen + 1][4];
  62. li g[maxlen + 1][3];
  63. ul gdiff[maxlen + 1][3];
  64. ul Case;
  65. li getg(li x, ul y, li diff, li fx)
  66. {
  67. if (x == fx) {
  68. return f[x][y] - x;
  69. }
  70. if (gdiff[x][y] == diff) {
  71. return g[x][y];
  72. }
  73. gdiff[x][y] = diff;
  74. return g[x][y] = std::max(f[x][y] - x, getg(x - diff, y, diff, fx));
  75. }
  76. int main()
  77. {
  78. std::scanf("%u", &T);
  79. for (Case = 1; Case <= T; ++Case) {
  80. pam.init();
  81. std::scanf("%s", str + 1);
  82. li len = std::strlen(str + 1);
  83. for (li x = 1; x <= len; ++x) {
  84. pam.add(str[x] - 'a');
  85. gdiff[x][0] = gdiff[x][1] = gdiff[x][2] = 0;
  86. for (ul y = 1; y <= 3; ++y) {
  87. f[x][y] = f[x - 1][y];
  88. for (ul las = pam.las; las; las = pam.st[las].anc) {
  89. li diff = pam.st[las].len - pam.st[pam.st[las].fa].len;
  90. li z = x - pam.st[pam.st[las].anc].len - diff;
  91. li fz = x - pam.st[las].len;
  92. f[x][y] = std::max(f[x][y], x + getg(z, y - 1, diff, fz));
  93. }
  94. }
  95. }
  96. std::printf("%u\n", f[len][3]);
  97. }
  98. return 0;
  99. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注