[关闭]
@qq290637843 2022-04-08T08:43:50.000000Z 字数 34546 阅读 384

2019徐州

题目见https://www.jisuanke.com/contest/6562/challenges

A、Cat

首先由于对任何

这说明要买的集合一定可以表示为一些严格分开的区间的并,其中每个区间都一次性买下。
现在注意对任何,所以对任何连续区间,可以求出其异或值。
如果的异或值小于等于,那么可以一次性买下,故只考虑其余情况。
现在默认
如果,那么由于,于是乎至多从首尾两个元素,一定能让异或值小于等于,故只需要分析是否能只损失一个:
奇:异或值一开始就小于等于,不在此考虑范围内。
偶:异或值小于等于
奇:异或值小于等于
偶:首先注意到,的异或值为,总之小于等于。现在考虑其他可能性:如果删掉一个奇数,则结果为再加上左边那段的异或值,总之大于等于,所以肯定不是最优的;而如果删掉一个偶数,则结果为再加上右边那段的异或值,而右边那段一定是左奇右偶的形式,除非删掉的就是,否则右边那段的异或值一定大于等于,这说明不会比直接删价格更小。
如果,注意非空区间中,除了,只有形如左偶右奇且长为的倍数的区间的异或值才为,于是:
奇:如果长为的倍数则无损失,如果长为,则损失任何一侧的两个都行。
偶:如果长为,则损失右侧三个即可,如果长为,则损失右侧一个即可。
奇:如果,如果长为,则损失左侧三个即可,如果长为,则损失左侧一个即可;如果,如果,则无损失,如果,则损失左侧一个即可。
偶:如果,如果长为,则损失左右各一个,再损失任何一侧的两个,如果长为,则损失左右各一个;如果,如果,则损失右侧一个,如果,则左右各损失一个。

  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. ull l, r, s;
  8. int main()
  9. {
  10. std::scanf("%u", &T);
  11. for (ul Case = 1; Case <= T; ++Case) {
  12. std::scanf("%llu%llu%llu", &l, &r, &s);
  13. ull ans;
  14. ull len = r - l + 1;
  15. if (r - l + 1 == 1) {
  16. if (s >= l) {
  17. ans = len;
  18. } else {
  19. ans = len - 1;
  20. }
  21. } else {
  22. if (((~r & 1) * r ^ (l & 1) * l ^ (len - (~r & 1) - (l & 1) >> 1 & 1)) <= s) {
  23. ans = len;
  24. } else {
  25. if (s >= 1) {
  26. if (l & 1) {
  27. if (r & 1) {
  28. ans = len - 1;
  29. } else {
  30. ans = (l ^ (len - 2 >> 1 & 1)) <= s ? len - 1 : len - 2;
  31. }
  32. } else {
  33. if (r & 1) {
  34. ans = len;
  35. } else {
  36. ans = len - 1;
  37. }
  38. }
  39. } else {
  40. if (l & 1) {
  41. if (r & 1) {
  42. if ((len & 3) == 3) {
  43. if (l == 1) {
  44. ans = len;
  45. } else {
  46. ans = len - 3;
  47. }
  48. } else {
  49. ans = len - 1;
  50. }
  51. } else {
  52. if ((len & 3) == 0) {
  53. if (l == 1) {
  54. ans = len - 1;
  55. } else {
  56. ans = len - 4;
  57. }
  58. } else {
  59. ans = len - 2;
  60. }
  61. }
  62. } else {
  63. if (r & 1) {
  64. if ((len & 3) == 0) {
  65. ans = len;
  66. } else {
  67. ans = len - 2;
  68. }
  69. } else {
  70. if ((len & 3) == 3) {
  71. ans = len - 3;
  72. } else {
  73. ans = len - 1;
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. if (ans) {
  81. std::printf("%llu\n", ans);
  82. } else {
  83. std::printf("-1\n");
  84. }
  85. }
  86. return 0;
  87. }

B、Cats line up

换成另一个描述:求如下图的有向哈密顿路的个数,点被编号为,其中两点之间有边当且仅当。于是可以状态压缩动态规划,由此可知固定时,此关于为线性递推数列。所以可以先算出一些前项然后伯莱坎普梅西。

  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 ull gfmul(ull a, ull b)
  10. {
  11. auto vc = _mm_clmulepi64_si128(_mm_cvtsi64_si128(a), _mm_cvtsi64_si128(b), 0);
  12. auto vf = _mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vc)), _mm_clmulepi64_si128(_mm_srli_si128(vc, 8), _mm_cvtsi64_si128(27ull), 0));
  13. return _mm_cvtsi128_si64(_mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vf)), _mm_clmulepi64_si128(_mm_srli_si128(vf, 8), _mm_cvtsi64_si128(27ull), 0)));
  14. }
  15. ull X, Y;
  16. std::mt19937_64 rnd;
  17. ull gethash(const std::vector<ul>& v)
  18. {
  19. ull ret = 1;
  20. for (ul i = 0; i != v.size(); i += 2) {
  21. ret = gfmul(ret, Y ^ gfmul(X ^ v[i], X ^ v[i + 1]));
  22. }
  23. return ret;
  24. }
  25. const ul mod = 998244353;
  26. ul plus(ul a, ul b)
  27. {
  28. return a + b < mod ? a + b : a + b - mod;
  29. }
  30. ul minus(ul a, ul b)
  31. {
  32. return a < b ? a + mod - b : a - b;
  33. }
  34. ul mul(ul a, ul b)
  35. {
  36. return ull(a) * ull(b) % mod;
  37. }
  38. void exgcd(li a, li b, li& x, li& y)
  39. {
  40. if (b) {
  41. exgcd(b, a % b, y, x);
  42. y -= a / b * x;
  43. } else {
  44. x = 1;
  45. y = 0;
  46. }
  47. }
  48. ul inverse(ul a)
  49. {
  50. li x, y;
  51. exgcd(a, mod, x, y);
  52. return x < 0 ? x + li(mod) : x;
  53. }
  54. class counter {
  55. public:
  56. std::vector<ul> v;
  57. ul cnt = 0;
  58. counter()=default;
  59. counter(const std::vector<ul>& a, ul b): v(a), cnt(b) {}
  60. counter(std::vector<ul>&& a, ul b): v(std::move(a)), cnt(b) {}
  61. };
  62. const ul maxn2 = 1e6;
  63. const ul maxn = 100;
  64. const ul maxk = 3;
  65. std::unordered_map<ull, counter> map[maxn + 1];
  66. void regular(std::vector<ul>& v, ul n, ul k)
  67. {
  68. for (ul i = 0; i != v.size(); ++i) {
  69. if (v[i] + k <= n) {
  70. v[i] = 0;
  71. }
  72. }
  73. }
  74. std::vector<ul> nextcon;
  75. bool check(std::vector<ul>& v)
  76. {
  77. ul cnt = 0;
  78. for (ul u : v) {
  79. if (!u) {
  80. ++cnt;
  81. if (cnt == 3) {
  82. return false;
  83. }
  84. }
  85. }
  86. return true;
  87. }
  88. ul ans[maxk + 1][maxn2 + 1];
  89. ul bm(const ul s[], ul cc[], ul nn)
  90. {
  91. static ul bb[1000];
  92. static ul tt[1000];
  93. cc[0] = 1;
  94. bb[0] = 1;
  95. ul tl;
  96. ul bl = 0;
  97. ul l = 0;
  98. ul m = 1;
  99. ul b = 1;
  100. for (ul n = 0; n != nn; ++n) {
  101. ul d = 0;
  102. for (ul i = 0; i <= l; ++i) {
  103. d = plus(d, mul(cc[i], s[n - i]));
  104. }
  105. if (d == 0) {
  106. ++m;
  107. } else if (l + l <= n) {
  108. std::memcpy(tt, cc, sizeof(ul) * (l + 1));
  109. tl = l;
  110. std::memset(&cc[l + 1], 0, sizeof(ul) * (n - l - l + 1));
  111. l = n + 1 - l;
  112. ul lambda = mul(inverse(b), d);
  113. for (ul i = 0; i <= bl; ++i) {
  114. cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));
  115. }
  116. bl = tl;
  117. std::memcpy(bb, tt, sizeof(ul) * (bl + 1));
  118. b = d;
  119. m = 1;
  120. } else {
  121. ul lambda = mul(inverse(b), d);
  122. for (ul i = 0; i <= bl; ++i) {
  123. cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));
  124. }
  125. ++m;
  126. }
  127. }
  128. return l;
  129. }
  130. ul cc[maxk + 1][1000];
  131. ul len[maxk + 1];
  132. ul T;
  133. int main()
  134. {
  135. rnd.seed(std::time(0));
  136. X = rnd();
  137. Y = rnd();
  138. ans[1][0] = 1;
  139. ans[2][0] = 1;
  140. ans[2][1] = 1;
  141. ans[3][0] = 1;
  142. ans[3][1] = 1;
  143. ans[3][2] = 2;
  144. for (ul k = 1; k <= 3; ++k) {
  145. map[k].clear();
  146. if (k == 1) {
  147. map[k][gethash({1, 1})] = counter({1, 1}, 1);
  148. } else if (k == 2) {
  149. map[k][gethash({1, 1, 2, 2})] = counter({1, 1, 2, 2}, 1);
  150. map[k][gethash({1, 2})] = counter({1, 2}, 1);
  151. } else if (k == 3) {
  152. map[k][gethash({1, 1, 2, 2, 3, 3})] = counter({1, 1, 2, 2, 3, 3}, 1);
  153. map[k][gethash({1, 2, 3, 3})] = counter({1, 2, 3, 3}, 1);
  154. map[k][gethash({1, 3, 2, 2})] = counter({1, 3, 2, 2}, 1);
  155. map[k][gethash({2, 3, 1, 1})] = counter({2, 3, 1, 1}, 1);
  156. map[k][gethash({1, 2})] = counter({1, 2}, 1);
  157. map[k][gethash({1, 3})] = counter({1, 3}, 1);
  158. map[k][gethash({2, 3})] = counter({2, 3}, 1);
  159. }
  160. for (ul n = k; n + 1 <= maxn; ++n) {
  161. map[n + 1].clear();
  162. for (const auto& p : map[n]) {
  163. const auto& con = p.second.v;
  164. ul val = p.second.cnt;
  165. for (ul i = 0; i + 1 != con.size(); ++i) {
  166. if (!con[i]) {
  167. continue;
  168. }
  169. if ((i & 1) && con[i - 1] == con[i]) {
  170. continue;
  171. }
  172. for (ul j = i + 1; j != con.size(); ++j) {
  173. if (!con[j]) {
  174. continue;
  175. }
  176. if ((j & 1) && con[j - 1] == con[j]) {
  177. continue;
  178. }
  179. if ((i >> 1) == (j >> 1)) {
  180. continue;
  181. }
  182. nextcon.resize(0);
  183. nextcon.push_back(con[i ^ 1]);
  184. nextcon.push_back(con[j ^ 1]);
  185. for (ul a = 0; a != con.size(); a += 2) {
  186. if ((a >> 1) != (i >> 1) && (a >> 1) != (j >> 1)) {
  187. nextcon.push_back(con[a]);
  188. nextcon.push_back(con[a + 1]);
  189. }
  190. }
  191. regular(nextcon, n + 1, k);
  192. if (!check(nextcon)) {
  193. continue;
  194. }
  195. auto& next = map[n + 1][gethash(nextcon)];
  196. next.v = nextcon;
  197. next.cnt = plus(next.cnt, val);
  198. }
  199. }
  200. for (ul i = 0; i != con.size(); ++i) {
  201. if (!con[i]) {
  202. continue;
  203. }
  204. if ((i & 1) && con[i - 1] == con[i]) {
  205. continue;
  206. }
  207. nextcon = con;
  208. nextcon[i] = n + 1;
  209. regular(nextcon, n + 1, k);
  210. if (!check(nextcon)) {
  211. continue;
  212. }
  213. auto& next = map[n + 1][gethash(nextcon)];
  214. next.v = nextcon;
  215. next.cnt = plus(next.cnt, val);
  216. }
  217. nextcon = con;
  218. nextcon.push_back(n + 1);
  219. nextcon.push_back(n + 1);
  220. regular(nextcon, n + 1, k);
  221. if (!check(nextcon)) {
  222. continue;
  223. }
  224. auto& next = map[n + 1][gethash(nextcon)];
  225. next.v = nextcon;
  226. next.cnt = plus(next.cnt, val);
  227. }
  228. }
  229. for (ul n = k; n <= maxn; ++n) {
  230. for (const auto& p : map[n]) {
  231. if (p.second.v.size() == 2) {
  232. ans[k][n] = plus(ans[k][n], p.second.cnt);
  233. }
  234. }
  235. if (n != 1) {
  236. ans[k][n] = mul(2, ans[k][n]);
  237. }
  238. }
  239. }
  240. for (ul k = 1; k <= 3; ++k) {
  241. len[k] = bm(ans[k], cc[k], maxn + 1);
  242. for (ul n = maxn + 1; n <= maxn2; ++n) {
  243. for (ul i = 1; i <= len[k]; ++i) {
  244. ans[k][n] = minus(ans[k][n], mul(cc[k][i], ans[k][n - i]));
  245. }
  246. }
  247. }
  248. std::scanf("%u", &T);
  249. for (ul Case = 1; Case <= T; ++Case) {
  250. ul n, k;
  251. std::scanf("%u%u", &n, &k);
  252. std::printf("%u\n", ans[k][n]);
  253. }
  254. return 0;
  255. }

C、<3 numbers

简单题

  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. ul T;
  10. ul l, r;
  11. ul mul(ul a, ul b, ul c)
  12. {
  13. return ull(a) * ull(b) % c;
  14. }
  15. ul pow(ul a, ul b, ul c)
  16. {
  17. ul ret = 1 % c;
  18. while (b) {
  19. if (b & 1) {
  20. ret = mul(ret, a, c);
  21. }
  22. a = mul(a, a, c);
  23. b >>= 1;
  24. }
  25. return ret;
  26. }
  27. std::mt19937 rnd;
  28. bool isprime(ul x)
  29. {
  30. if (x == 1) {
  31. return true;
  32. }
  33. if (x == 2) {
  34. return true;
  35. }
  36. if (~x & 1) {
  37. return false;
  38. }
  39. ul t = __builtin_ctz(x - 1);
  40. ul s = x - 1 >> t;
  41. for (ul cnt = 1; cnt <= 20; ++cnt) {
  42. ul k = pow(rnd() % (x - 1) + 1, s, x);
  43. if (k == 1) {
  44. continue;
  45. }
  46. ul i = 0;
  47. while (k != 1 && k != x - 1 && i + 1 != t) {
  48. ++i;
  49. k = mul(k, k, x);
  50. }
  51. if (k != x - 1) {
  52. return false;
  53. }
  54. }
  55. return true;
  56. }
  57. int main()
  58. {
  59. rnd.seed(std::time(0));
  60. std::scanf("%u", &T);
  61. for (ul Case = 1; Case <= T; ++Case) {
  62. std::scanf("%u%u", &l, &r);
  63. if (r - l + 1 >= 420) {
  64. std::printf("Yes\n");
  65. continue;
  66. }
  67. ul x = 0;
  68. for (ul i = l; i <= r; ++i) {
  69. x += isprime(i);
  70. }
  71. std::printf(ull(x) * 3 < r - l + 1 ? "Yes\n" : "No\n");
  72. }
  73. return 0;
  74. }

D、Polycut

首先,关于割的那刀这样处理:对任何一个用点棱存储的凸多面体,如果多加一个约束,只需要研究这个约束和那些点或者边相交了,就能得到一个新的用点棱存储的凸多面体。
现在解决给定一个点棱存储的凸多面体的体积问题。首先是要解决一个点所连出去的边的排序问题。这个问题这样解决,考虑先将所有点的重心找到,记为,接着,对每个点,将其连出去的边投影到和相垂直的平面上,于是就可以以为极点对边进行极角排序,这样就知道每次走完一条边之后,接下来哪条边才是“向左转”该走的了。于是可以求出所有面,再接着就是很简单的工作了。
过了,数据没有问题。

  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 llf = long double;
  10. const ull mod = 4179340454199820289ull;
  11. ull plus(ull a, ull b)
  12. {
  13. return a + b < mod ? a + b : a + b - mod;
  14. }
  15. ull minus(ull a, ull b)
  16. {
  17. return a < b ? a + mod - b : a - b;
  18. }
  19. ull mul(ll a, ll b)
  20. {
  21. ll tmp = a * b - ll(llf(a) * llf(b) / llf(mod)) * ll(mod);
  22. return tmp < 0 ? tmp + ll(mod) : (tmp < ll(mod) ? tmp : tmp - ll(mod));
  23. }
  24. void exgcd(ll a, ll b, ll& x, ll& y)
  25. {
  26. if (b) {
  27. exgcd(b, a % b, y, x);
  28. y -= a / b * x;
  29. } else {
  30. x = 1;
  31. y = 0;
  32. }
  33. }
  34. ull inverse(ull a)
  35. {
  36. ll x, y;
  37. exgcd(a, mod, x, y);
  38. return x < 0 ? x + ll(mod) : x;
  39. }
  40. class hashllf {
  41. public:
  42. llf val = 0;
  43. ull hash = 0;
  44. hashllf()=default;
  45. hashllf(li x): val(x), hash((x + mod) % mod) {}
  46. hashllf(llf x): val(x), hash(0) {}
  47. hashllf(llf a, ull b): val(a), hash(b) {}
  48. operator llf() const {
  49. return val;
  50. }
  51. };
  52. hashllf operator+(const hashllf& a, const hashllf& b)
  53. {
  54. return hashllf(a.val + b.val, plus(a.hash, b.hash));
  55. }
  56. hashllf operator-(const hashllf& a, const hashllf& b)
  57. {
  58. return hashllf(a.val - b.val, minus(a.hash, b.hash));
  59. }
  60. hashllf operator*(const hashllf& a, const hashllf& b)
  61. {
  62. return hashllf(a.val * b.val, mul(a.hash, b.hash));
  63. }
  64. hashllf operator/(const hashllf& a, const hashllf& b)
  65. {
  66. return hashllf(a.val / b.val, mul(a.hash, inverse(b.hash)));
  67. }
  68. li sgn(const hashllf& x)
  69. {
  70. return x.hash == 0 ? 0 : (x.val < 0 ? -1 : 1);
  71. }
  72. class vec {
  73. public:
  74. hashllf x = 0;
  75. hashllf y = 0;
  76. hashllf z = 0;
  77. vec()=default;
  78. vec(hashllf a, hashllf b, hashllf c): x(a), y(b), z(c) {}
  79. ul high() const {
  80. return sgn(x) ? 3 : (sgn(y) ? 2 : (sgn(z) ? 1 : 0));
  81. }
  82. hashllf& operator[](ul i) {
  83. return i == 1 ? z : (i == 2 ? y : x);
  84. }
  85. const hashllf& operator[](ul i) const {
  86. return i == 1 ? z : (i == 2 ? y : x);
  87. }
  88. };
  89. vec operator+(const vec& a, const vec& b)
  90. {
  91. return vec(a.x + b.x, a.y + b.y, a.z + b.z);
  92. }
  93. vec operator-(const vec& a, const vec& b)
  94. {
  95. return vec(a.x - b.x, a.y - b.y, a.z - b.z);
  96. }
  97. vec operator*(hashllf a, const vec& b)
  98. {
  99. return vec(a * b.x, a * b.y, a * b.z);
  100. }
  101. vec operator*(const vec& a, hashllf b)
  102. {
  103. return vec(a.x * b, a.y * b, a.z * b);
  104. }
  105. vec operator/(const vec& a, hashllf b)
  106. {
  107. return vec(a.x / b, a.y / b, a.z / b);
  108. }
  109. hashllf operator*(const vec& a, const vec& b)
  110. {
  111. return a.x * b.x + a.y * b.y + a.z * b.z;
  112. }
  113. ul n, m, k;
  114. ul totp;
  115. vec points[1 << 21];
  116. ul tote;
  117. std::pair<ul, ul> edges[1 << 21];
  118. std::vector<ul> pstack[4];
  119. std::vector<ul> estack[4];
  120. vec cutdir[4];
  121. vec cutx[4];
  122. vec cuty[4];
  123. hashllf cutbound[4];
  124. li type[1 << 21];
  125. std::vector<ul> tmpstack;
  126. std::priority_queue<llf, std::vector<llf>, std::greater<llf>> queue;
  127. llf myabs(llf x)
  128. {
  129. return x < 0 ? -x : x;
  130. }
  131. class mygreater {
  132. public:
  133. bool operator()(llf a, llf b){return myabs(a) > myabs(b);}
  134. };
  135. std::priority_queue<llf, std::vector<llf>, mygreater> queue2;
  136. llf getsum()
  137. {
  138. while (queue2.size() >= 2) {
  139. llf a = queue2.top();
  140. queue2.pop();
  141. llf b = queue2.top();
  142. queue2.pop();
  143. queue2.push(a + b);
  144. }
  145. llf tmp = queue2.top();
  146. queue2.pop();
  147. return tmp;
  148. }
  149. vec getw(const std::vector<ul>& pstack)
  150. {
  151. vec ret(0, 0, 0);
  152. for (auto p : pstack) {
  153. ret = ret + points[p];
  154. }
  155. ret = ret / hashllf(li(pstack.size()));
  156. for (auto p : pstack) {
  157. queue2.push(points[p].x);
  158. }
  159. ret.x.val = getsum() / llf(pstack.size());
  160. for (auto p : pstack) {
  161. queue2.push(points[p].y);
  162. }
  163. ret.y.val = getsum() / llf(pstack.size());
  164. for (auto p : pstack) {
  165. queue2.push(points[p].z);
  166. }
  167. ret.z.val = getsum() / llf(pstack.size());
  168. return ret;
  169. }
  170. hashllf vol1(const vec& a)
  171. {
  172. return a * a;
  173. }
  174. hashllf vol2(const vec& a, const vec& b)
  175. {
  176. hashllf aa = a * a;
  177. hashllf bb = b * b;
  178. hashllf ab = a * b;
  179. return aa * bb - ab * ab;
  180. }
  181. hashllf vol3(const vec& a, const vec& b, const vec& c)
  182. {
  183. hashllf aa = a * a;
  184. hashllf ab = a * b;
  185. hashllf ac = a * c;
  186. hashllf bb = b * b;
  187. hashllf bc = b * c;
  188. hashllf cc = c * c;
  189. return aa * bb * cc + hashllf(2) * ab * bc * ac - ac * bb * ac - aa * bc * bc - ab * ab * cc;
  190. }
  191. hashllf vol3p(const vec& a, const vec& b, const vec& c)
  192. {
  193. return a.x * b.y * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.x * b.z * c.y - a.y * b.x * c.z - a.z * b.y * c.x;
  194. }
  195. void insert(std::vector<vec>& base, vec v)
  196. {
  197. for (const auto u : base) {
  198. ul uh = u.high();
  199. if (sgn(v[uh])) {
  200. v = v - v[uh] / u[uh] * u;
  201. }
  202. }
  203. if (sgn(v.x) || sgn(v.y) || sgn(v.z)) {
  204. base.push_back(v);
  205. }
  206. }
  207. ul checkdim(const std::vector<ul>& pstack, vec& w)
  208. {
  209. static std::vector<vec> base;
  210. base.resize(0);
  211. w = getw(pstack);
  212. for (auto p : pstack) {
  213. insert(base, points[p] - w);
  214. }
  215. return base.size();
  216. }
  217. ul region(llf x, llf y)
  218. {
  219. return x < 0 ? (y < 0 ? 3 : 2) : (y < 0 ? 4 : 1);
  220. }
  221. std::vector<llf> ans;
  222. std::vector<ul> neibor[1 << 20];
  223. std::unordered_map<ull, ul> nextto;
  224. std::unordered_set<ull> already;
  225. ull base;
  226. std::mt19937_64 rnd;
  227. inline ull gfmul(ull a, ull b)
  228. {
  229. auto vc = _mm_clmulepi64_si128(_mm_cvtsi64_si128(a), _mm_cvtsi64_si128(b), 0);
  230. auto vf = _mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vc)), _mm_clmulepi64_si128(_mm_srli_si128(vc, 8), _mm_cvtsi64_si128(27ull), 0));
  231. return _mm_cvtsi128_si64(_mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vf)), _mm_clmulepi64_si128(_mm_srli_si128(vf, 8), _mm_cvtsi64_si128(27ull), 0)));
  232. }
  233. std::set<ull> eset[4];
  234. void search(ul cutid)
  235. {
  236. if (cutid == k + 1) {
  237. if (pstack[k].empty()) {
  238. ans.push_back(0);
  239. return;
  240. }
  241. vec w = getw(pstack[k]);
  242. for (ul p : pstack[k]) {
  243. neibor[p].resize(0);
  244. }
  245. for (const auto e : estack[k]) {
  246. neibor[edges[e].first].push_back(edges[e].second);
  247. neibor[edges[e].second].push_back(edges[e].first);
  248. }
  249. nextto.clear();
  250. for (auto p : pstack[k]) {
  251. vec z = points[p] - w;
  252. z = z / std::sqrt(z * z);
  253. vec sq;
  254. llf val = 0;
  255. for (auto q : neibor[p]) {
  256. llf newval = vol2(points[q] - points[p], z);
  257. if (val < newval) {
  258. sq = points[q];
  259. val = newval;
  260. }
  261. }
  262. vec x = sq - points[p];
  263. x = x - x * z * z;
  264. x = x / std::sqrt(x * x);
  265. vec y(z.y * x.z - z.z * x.y, z.z * x.x - z.x * x.z, z.x * x.y - z.y * x.x);
  266. sort(neibor[p].begin(), neibor[p].end(), [&](ul a, ul b) {
  267. llf ax = (points[a] - points[p]) * x;
  268. llf ay = (points[a] - points[p]) * y;
  269. llf bx = (points[b] - points[p]) * x;
  270. llf by = (points[b] - points[p]) * y;
  271. return region(ax, ay) != region(bx, by) ? region(ax, ay) < region(bx, by) : ax * by - ay * bx > 0;});
  272. neibor[p].push_back(neibor[p].front());
  273. for (ul i = 0; i + 1 != neibor[p].size(); ++i) {
  274. nextto[gfmul(base ^ neibor[p][i + 1], p)] = neibor[p][i];
  275. }
  276. }
  277. already.clear();
  278. while (queue.size()) {
  279. queue.pop();
  280. }
  281. for (auto p : pstack[k]) {
  282. neibor[p].pop_back();
  283. for (ul q : neibor[p]) {
  284. if (!already.insert(gfmul(base ^ p, q)).second) {
  285. continue;
  286. }
  287. for (ul i = q, j = nextto[gfmul(base ^ p, q)]; ; ) {
  288. queue.push(myabs(vol3p(points[p] - w, points[i] - w, points[j] - w)));
  289. ul newj = nextto[gfmul(base ^ i, j)];
  290. already.insert(gfmul(base ^ i, j));
  291. i = j;
  292. j = newj;
  293. if (j == p) {
  294. already.insert(gfmul(base ^ i, j));
  295. break;
  296. }
  297. }
  298. }
  299. }
  300. while (queue.size() >= 2) {
  301. llf a = queue.top();
  302. queue.pop();
  303. llf b = queue.top();
  304. queue.pop();
  305. queue.push(a + b);
  306. }
  307. ans.push_back(queue.top() / 6);
  308. return;
  309. }
  310. for (li pn : {1, -1}) {
  311. pstack[cutid].resize(0);
  312. estack[cutid].resize(0);
  313. eset[cutid].clear();
  314. if (pstack[cutid - 1].empty()) {
  315. search(cutid + 1);
  316. }
  317. tmpstack.resize(0);
  318. for (ul p : pstack[cutid - 1]) {
  319. type[p] = sgn(cutdir[cutid] * points[p] - cutbound[cutid]) * pn;
  320. if (type[p] <= 0) {
  321. pstack[cutid].push_back(p);
  322. }
  323. if (type[p] == 0) {
  324. tmpstack.push_back(p);
  325. }
  326. }
  327. for (ul e : estack[cutid - 1]) {
  328. if (type[edges[e].first] <= 0 && type[edges[e].second] <= 0) {
  329. estack[cutid].push_back(e);
  330. eset[cutid].insert(gfmul(edges[e].first ^ base, edges[e].second ^ base));
  331. }
  332. if (type[edges[e].first] * type[edges[e].second] < 0) {
  333. const auto& a = points[edges[e].first];
  334. const auto& b = points[edges[e].second];
  335. ++totp;
  336. points[totp] = (cutbound[cutid] - a * cutdir[cutid]) / ((b - a) * cutdir[cutid]) * b + (cutbound[cutid] - b * cutdir[cutid]) / ((a - b) * cutdir[cutid]) * a;
  337. tmpstack.push_back(totp);
  338. pstack[cutid].push_back(totp);
  339. type[totp] = -1;
  340. ++tote;
  341. edges[tote].first = type[edges[e].first] < type[edges[e].second] ? edges[e].first : edges[e].second;
  342. edges[tote].second = totp;
  343. estack[cutid].push_back(tote);
  344. eset[cutid].insert(gfmul(edges[tote].first ^ base, edges[tote].second ^ base));
  345. }
  346. }
  347. if (tmpstack.size()) {
  348. vec w;
  349. ul dim = checkdim(tmpstack, w);
  350. if (dim != 0) {
  351. llf val = 0;
  352. ul sp;
  353. for (ul p : tmpstack) {
  354. llf newval = vol1(points[p] - w);
  355. if (val < newval) {
  356. val = newval;
  357. sp = p;
  358. }
  359. }
  360. vec x = (points[sp] - w) / std::sqrt(vol1(points[sp] - w));
  361. vec z = cutdir[cutid] / std::sqrt(vol1(cutdir[cutid]));
  362. vec y(z.y * x.z - z.z * x.y, z.z * x.x - z.x * x.z, z.x * x.y - z.y * x.x);
  363. if (dim == 1) {
  364. std::sort(tmpstack.begin(), tmpstack.end(), [&](ul a, ul b){return points[a] * x < points[b] * x;});
  365. for (ul i = 0; i + 1 != tmpstack.size(); ++i) {
  366. if (eset[cutid].find(gfmul(tmpstack[i] ^ base, tmpstack[i + 1] ^ base)) == eset[cutid].end()) {
  367. ++tote;
  368. edges[tote].first = tmpstack[i];
  369. edges[tote].second = tmpstack[i + 1];
  370. estack[cutid].push_back(tote);
  371. eset[cutid].insert(gfmul(edges[tote].first ^ base, edges[tote].second ^ base));
  372. }
  373. }
  374. } else if (dim == 2) {
  375. std::sort(tmpstack.begin(), tmpstack.end(), [&](ul a, ul b){
  376. llf ax = (points[a] - w) * x;
  377. llf ay = (points[a] - w) * y;
  378. llf bx = (points[b] - w) * x;
  379. llf by = (points[b] - w) * y;
  380. return region(ax, ay) != region(bx, by) ? region(ax, ay) < region(bx, by) : ax * by - ay * bx > 0;});
  381. tmpstack.push_back(tmpstack.front());
  382. for (ul i = 0; i + 1 != tmpstack.size(); ++i) {
  383. if (type[tmpstack[i]] != 0 || type[tmpstack[i + 1]] != 0) {
  384. ++tote;
  385. edges[tote].first = tmpstack[i];
  386. edges[tote].second = tmpstack[i + 1];
  387. estack[cutid].push_back(tote);
  388. }
  389. }
  390. }
  391. }
  392. }
  393. if (pstack[cutid].size()) {
  394. vec w;
  395. ul dim = checkdim(pstack[cutid], w);
  396. if (dim < 3) {
  397. pstack[cutid].resize(0);
  398. }
  399. }
  400. search(cutid + 1);
  401. }
  402. }
  403. int main()
  404. {
  405. rnd.seed(std::time(0));
  406. base = rnd();
  407. std::scanf("%u%u%u", &n, &m, &k);
  408. for (ul i = 1; i <= n; ++i) {
  409. li x, y, z;
  410. std::scanf("%d%d%d", &x, &y, &z);
  411. points[totp] = vec(x, y, z);
  412. pstack[0].push_back(totp);
  413. ++totp;
  414. }
  415. --totp;
  416. for (ul i = 1; i <= m; ++i) {
  417. ++tote;
  418. std::scanf("%u%u", &edges[tote].first, &edges[tote].second);
  419. estack[0].push_back(tote);
  420. }
  421. for (ul i = 1; i <= k; ++i) {
  422. li a, b, c, d;
  423. std::scanf("%d%d%d%d", &a, &b, &c, &d);
  424. cutdir[i] = vec(a, b, c);
  425. cutbound[i] = d;
  426. }
  427. search(1);
  428. std::sort(ans.begin(), ans.end());
  429. for (const auto& a : ans) {
  430. std::printf("%.20Le\n", a);
  431. }
  432. return 0;
  433. }

E、Multiply

简单题

  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 llf = long double;
  10. ul T;
  11. ull plus(ull a, ull b, ull c)
  12. {
  13. return a + b < c ? a + b : a + b - c;
  14. }
  15. ull minus(ull a, ull b, ull c)
  16. {
  17. return a < b ? a + c - b : a - b;
  18. }
  19. ll mul(ll a, ll b, ll c)
  20. {
  21. ll tmp = a * b - ll(llf(a) * llf(b) / llf(c)) * c;
  22. return tmp < 0 ? tmp + c : (tmp < c ? tmp : tmp - c);
  23. }
  24. ull pow(ull a, ull b, ull c)
  25. {
  26. ull ret = 1 % c;
  27. while (b) {
  28. if (b & 1) {
  29. ret = mul(ret, a, c);
  30. }
  31. a = mul(a, a, c);
  32. b >>= 1;
  33. }
  34. return ret;
  35. }
  36. std::mt19937_64 rnd;
  37. bool isprime(ull x)
  38. {
  39. if (x == 1) {
  40. return true;
  41. }
  42. if (x == 2) {
  43. return true;
  44. }
  45. if (~x & 1) {
  46. return false;
  47. }
  48. ul t = __builtin_ctzll(x - 1);
  49. ull s = x - 1 >> t;
  50. for (ul cnt = 1; cnt <= 20; ++cnt) {
  51. ull k = pow(rnd() % (x - 1) + 1, s, x);
  52. if (k == 1) {
  53. continue;
  54. }
  55. ul i = 0;
  56. while (k != 1 && k != x - 1 && i + 1 != t) {
  57. ++i;
  58. k = mul(k, k, x);
  59. }
  60. if (k != x - 1) {
  61. return false;
  62. }
  63. }
  64. return true;
  65. }
  66. ull gcd(ull a, ull b)
  67. {
  68. while (b) {
  69. b ^= a ^= b ^= a %= b;
  70. }
  71. return a;
  72. }
  73. ull rho(ull v)
  74. {
  75. while (true) {
  76. ull c = rnd() % (v - 1) + 1;
  77. auto f = [&](ull x){return plus(mul(x, x, v), c, v);};
  78. ull x = rnd() % v;
  79. ull y = f(x);
  80. while (x != y) {
  81. ull tmp = gcd(minus(x, y, v), v);
  82. if (tmp != 1) {
  83. return tmp;
  84. }
  85. x = f(x);
  86. y = f(f(y));
  87. }
  88. }
  89. }
  90. std::vector<ull> facs;
  91. void getfact(ull x)
  92. {
  93. static std::vector<ull> stack;
  94. stack.resize(0);
  95. facs.resize(0);
  96. if (x != 1) {
  97. stack.push_back(x);
  98. }
  99. while (stack.size()) {
  100. ull curr = stack.back();
  101. stack.pop_back();
  102. if (isprime(curr)) {
  103. facs.push_back(curr);
  104. } else {
  105. ull next = rho(curr);
  106. stack.push_back(next);
  107. stack.push_back(curr / next);
  108. }
  109. }
  110. std::sort(facs.begin(), facs.end());
  111. }
  112. ul n;
  113. ull a;
  114. ull x, y;
  115. std::vector<std::pair<ull, ull>> faccntx;
  116. std::vector<std::pair<ull, ull>> faccnty;
  117. int main()
  118. {
  119. rnd.seed(std::time(0));
  120. std::scanf("%u", &T);
  121. for (ul Case = 1; Case <= T; ++Case) {
  122. std::scanf("%u%llu%llu", &n, &x, &y);
  123. getfact(x);
  124. std::sort(facs.begin(), facs.end());
  125. faccntx.resize(0);
  126. for (auto p : facs) {
  127. if (faccntx.empty() || faccntx.back().first != p) {
  128. faccntx.push_back(std::pair<ull, ul>(p, 1));
  129. } else {
  130. ++faccntx.back().second;
  131. }
  132. }
  133. faccnty = faccntx;
  134. for (auto& pc : faccnty) {
  135. ull p = pc.first;
  136. pc.second = 0;
  137. ull pi = p;
  138. ull tmp = y / p;
  139. while (true) {
  140. pc.second += y / pi;
  141. if (pi > tmp) {
  142. break;
  143. } else {
  144. pi *= p;
  145. }
  146. }
  147. }
  148. for (ul i = 1; i <= n; ++i) {
  149. std::scanf("%llu", &a);
  150. for (auto& pc : faccnty) {
  151. ull p = pc.first;
  152. ull pi = p;
  153. ull tmp = a / p;
  154. while (true) {
  155. pc.second -= a / pi;
  156. if (pi > tmp) {
  157. break;
  158. } else {
  159. pi *= p;
  160. }
  161. }
  162. }
  163. }
  164. ull ans = 2e18;
  165. for (ull i = 0; i != faccntx.size(); ++i) {
  166. ans = std::min(ans, faccnty[i].second / faccntx[i].second);
  167. }
  168. std::printf("%llu\n", ans);
  169. }
  170. return 0;
  171. }

F、The Answer to the Ultimate Question of Life, The Universe, and Everything.

简单题

  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 llf = long double;
  10. const ll maxv = 5000;
  11. const ll maxx = 200;
  12. std::string ans[maxx + 1];
  13. ll upcbrt(ll x)
  14. {
  15. ll tmp = std::llround(std::cbrt(llf(x)));
  16. while (tmp * tmp * tmp < x) {
  17. ++tmp;
  18. }
  19. return tmp;
  20. }
  21. std::string tmp;
  22. std::stringstream ss;
  23. int main()
  24. {
  25. for (ll a = -maxv, a3 = a * a * a; a3 * 3 <= maxx; ++a, a3 = a * a * a) {
  26. for (ll b = std::max(upcbrt(-maxv * maxv * maxv - a3), a), b3 = b * b * b; b <= maxv && a3 + b3 * 2 <= maxx; ++b, b3 = b * b * b) {
  27. for (ll c = std::max(upcbrt(-a * a * a - b * b * b), b), c3 = c * c * c; c <= maxv && a3 + b3 + c3 <= maxx; ++c, c3 = c * c * c) {
  28. ll v = a3 + b3 + c3;
  29. ss.str("");
  30. ss << a << ' ' << b << ' ' << c;
  31. tmp = ss.str();
  32. if (ans[v].empty() || ans[v].size() > tmp.size()) {
  33. std::swap(ans[v], tmp);
  34. }
  35. }
  36. }
  37. }
  38. std::freopen("Fdata.txt", "w", stdout);
  39. std::printf("{");
  40. for (ul i = 0; i <= maxx; ++i) {
  41. if (i) {
  42. std::printf(",");
  43. }
  44. std::cout << '\"' << ans[i] << '\"';
  45. }
  46. std::printf("}");
  47. return 0;
  48. }
  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 ll maxx = 200;
  10. std::string ans[maxx + 1] = {"0 0 0","0 0 1","0 1 1","1 1 1","","","-1 -1 2","-1 0 2","0 0 2","0 1 2","1 1 2","-2 -2 3","-11 7 10","","","-1 2 2","0 2 2","1 2 2","-2 -1 3","-2 0 3","-2 1 3","-86 28 85","","","2 2 2","-1 -1 3","-1 0 3","0 0 3","0 1 3","1 1 3","","","","","-6 5 5","0 2 3","1 2 3","-3 0 4","-3 1 4","","","","","2 2 3","-7 -5 8","-3 2 4","-2 3 3","-8 6 7","-2 -2 4","","","-796 602 659","","-1 3 3","0 3 3","1 3 3","-2 0 4","-2 1 4","","","-4 -1 5","-4 0 5","2 3 3","-1 0 4","0 0 4","0 1 4","1 1 4","","","-4 2 5","-64 23 63","-1 2 4","0 2 4","1 2 4","","","","","-55 26 53","-66 -49 74","2 2 4","3 3 3","-11 -11 14","-2 3 4","","","","-4126 -1972 4271","-4 3 5","-7 6 6","-1 3 4","0 3 4","1 3 4","-5 -5 7","","","-22 14 20","-3 -1 5","-3 0 5","2 3 4","-6 -3 7","-3 4 4","-239 118 229","","","-7 -4 8","-3 2 5","-48 -28 51","-1165 -948 1345","-2 -2 5","","-881 -296 892","","","","-12 8 11","-2 -1 5","-2 0 5","3 3 4","-6 -2 7","-2 4 4","","","-1 -1 5","-1 0 5","0 0 5","0 1 5","1 1 5","0 4 4","1 4 4","","","-1 2 5","0 2 5","1 2 5","-6 2 7","2 4 4","-11 -9 13","-86 -77 103","","","2 2 5","-7 -3 8","","-2 3 5","-8 -7 10","-9 -5 10","-56 -50 67","","","-367 260 317","-1 3 5","0 3 5","1 3 5","-6 3 7","3 4 4","","","","-130 80 119","2 3 5","-7 -2 8","-3 4 5","-76 -68 91","-66 -59 79","","","","-7 -1 8","-7 0 8","-7 1 8","-6 -5 8","","","-8 7 7","","","-7 2 8","-13 -10 15","3 3 5","","-2 4 5","-14 9 13","-17 10 16","","","-4 5 5","-58 27 56","-1 4 5","0 4 5","1 4 5","-6 4 7","4 4 4","","","","-7 3 8","2 4 5","-48 -19 49","-24 15 22","-2 -2 6"};
  11. ul T;
  12. ul x;
  13. int main()
  14. {
  15. std::cin >> T;
  16. for (ul Case = 1; Case <= T; ++Case) {
  17. std::cin >> x;
  18. std::cout << (ans[x].empty() ? std::string("impossible") : ans[x]) << std::endl;
  19. }
  20. return 0;
  21. }

G、Factory

下文中,原题是要在满足:

的情况下最小化:
这不是一个标准的线性规划问题,现在引入一个新的变量,将问题改为在满足:
的情况下最小化:
接着,借助于强对偶定理(该定理的证明异常冗长,就不给出了),将问题对偶为在满足:
的情况下最大化:
而该问题实际显然和如下问题等价,在满足:
的情况下最大化
现在变成一个在维仿射空间里最大化一个非光滑凹函数的问题,也就是在仿射空间里最小化非光滑凸函数的问题。
由于非光滑,所以有些点并没有梯度,于是现在定义次梯度。
考虑欧式仿射空间(用表示的切空间的对偶空间)上有一凸函数,那么显然
所有满足这样条件的,均称为处的次梯度。而显然,对任何一组凸函数,如果分别是它们在处的次梯度,那么也是是的次梯度。注意,处的次梯度并不意味着在某个单调递减,这意味着将移动到并不保证是下降的,于是次梯度算法并不称为次梯度下降算法。但是整体来说,只要步长设置满足一定要求,一定能收敛到最值点。关于这一点以及收敛速度的证明见:https://www.zybuluo.com/qq290637843/note/1776595
接下来求次梯度:首先固定,设是使得最小的。那么具有次梯度
其中。故整体的次梯度为
而依据,那么的移动量为
但是这样收敛还是太慢了,个人将的定义换为“估计答案和当前答案的差”,其中“估计答案”是指当前最大答案乘的系数。正确性不会证。(这种自适应次梯度算法实际叫做Polyak's step length)

  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 llf = long double;
  10. using lf = double;
  11. using d_t = lf;
  12. const ul maxn = 2e4;
  13. const ul maxk = 50;
  14. ul n, k;
  15. d_t t[maxn + 1][maxk + 1];
  16. d_t g[maxk + 1];
  17. d_t xchange[maxk + 1];
  18. bool gequal0;
  19. d_t M;
  20. d_t A;
  21. d_t T;
  22. d_t Acurr;
  23. const d_t beta = 0.00995;
  24. ull start;
  25. void f(d_t x[])
  26. {
  27. std::memset(g + 1, 0, sizeof(d_t) * k);
  28. d_t sum = 0;
  29. for (ul j = 1; j <= k; ++j) {
  30. sum += x[j];
  31. }
  32. for (ul j = 1; j <= k; ++j) {
  33. x[j] /= sum;
  34. }
  35. sum = 0;
  36. d_t gsum = 0;
  37. for (ul i = 1; i <= n; ++i) {
  38. d_t mn = t[i][1] * x[1];
  39. ul a = 1;
  40. for (ul j = 2; j <= k; ++j) {
  41. if (t[i][j] * x[j] < mn) {
  42. mn = t[i][j] * x[j];
  43. a = j;
  44. }
  45. }
  46. g[a] += t[i][a];
  47. sum += mn;
  48. }
  49. A = std::max(A, sum);
  50. Acurr = sum;
  51. T = (1 + beta) * A - Acurr;
  52. gequal0 = true;
  53. for (ul j = 1; j <= k; ++j) {
  54. gsum += g[j];
  55. g[j] *= k;
  56. if (g[j] != g[1]) {
  57. gequal0 = false;
  58. }
  59. }
  60. if (gequal0) {
  61. return;
  62. }
  63. for (ul j = 1; j <= k; ++j) {
  64. g[j] -= gsum;
  65. }
  66. d_t tmp = 0;
  67. for (ul j = 1; j <= k; ++j) {
  68. tmp += g[j] * g[j];
  69. }
  70. for (ul j = 1; j <= k; ++j) {
  71. xchange[j] = T * k * (g[j] / tmp);
  72. }
  73. }
  74. d_t x[maxk + 1];
  75. int main()
  76. {
  77. std::scanf("%u%u", &n, &k);
  78. for (ul i = 1; i <= n; ++i) {
  79. for (ul j = 1; j <= k; ++j) {
  80. ul tmp;
  81. std::scanf("%u", &tmp);
  82. t[i][j] = tmp;
  83. }
  84. }
  85. for (ul j = 1; j <= k; ++j) {
  86. x[j] = d_t(1) / d_t(k);
  87. }
  88. start = std::clock();
  89. while (std::clock() - start < CLOCKS_PER_SEC * 2.9) {
  90. f(x);
  91. if (gequal0) {
  92. std::printf("%.20lf\n", lf(A));
  93. return 0;
  94. }
  95. for (ul j = 1; j <= k; ++j) {
  96. x[j] += xchange[j];
  97. }
  98. }
  99. std::printf("%.20lf\n", lf(A));
  100. return 0;
  101. }

H、Yuuki and a problem

注意对于一个可重正整数集,如果其能表示出,则其能表示出,且此条件是充要的。于是原题变为次区间查询小于等于指定数的数之和,线段树套树堆即可。不知道为什么会给十五秒的时限。

  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. ul n, q;
  10. std::mt19937_64 rnd;
  11. class node {
  12. public:
  13. ul val = 0;
  14. ul cnt = 0;
  15. ull sum = 0;
  16. ul lson = 0;
  17. ul rson = 0;
  18. ull weight = 0;
  19. node() {
  20. weight = rnd();
  21. }
  22. };
  23. ul stack[1 << 22];
  24. ul remain = 0;
  25. ul tot = 0;
  26. node tree[1 << 22];
  27. void update(ul x)
  28. {
  29. tree[x].sum = tree[x].val * ull(tree[x].cnt) + tree[tree[x].lson].sum + tree[tree[x].rson].sum;
  30. }
  31. void lrotate(ul& x)
  32. {
  33. ul y = tree[x].rson;
  34. tree[x].rson = tree[y].lson;
  35. tree[y].lson = x;
  36. update(x);
  37. update(y);
  38. x = y;
  39. }
  40. void rrotate(ul& x)
  41. {
  42. ul y = tree[x].lson;
  43. tree[x].lson = tree[y].rson;
  44. tree[y].rson = x;
  45. update(x);
  46. update(y);
  47. x = y;
  48. }
  49. void insert(ul& x, ul v)
  50. {
  51. if (!x) {
  52. if (remain) {
  53. x = stack[remain];
  54. --remain;
  55. } else {
  56. ++tot;
  57. x = tot;
  58. }
  59. tree[x] = node();
  60. tree[x].val = v;
  61. tree[x].cnt = 1;
  62. update(x);
  63. return;
  64. }
  65. if (tree[x].val == v) {
  66. ++tree[x].cnt;
  67. update(x);
  68. } else if (tree[x].val < v) {
  69. insert(tree[x].rson, v);
  70. update(x);
  71. if (tree[x].weight < tree[tree[x].rson].weight) {
  72. lrotate(x);
  73. }
  74. } else if (tree[x].val > v) {
  75. insert(tree[x].lson, v);
  76. update(x);
  77. if (tree[x].weight < tree[tree[x].lson].weight) {
  78. rrotate(x);
  79. }
  80. }
  81. }
  82. void erase(ul& x, ul v)
  83. {
  84. if (tree[x].val == v) {
  85. if (tree[x].cnt >= 2) {
  86. --tree[x].cnt;
  87. update(x);
  88. return;
  89. }
  90. if (!tree[x].lson || !tree[x].rson) {
  91. ++remain;
  92. stack[remain] = x;
  93. x = tree[x].lson ^ tree[x].rson;
  94. } else if (tree[tree[x].lson].weight > tree[tree[x].rson].weight) {
  95. rrotate(x);
  96. erase(x, v);
  97. } else {
  98. lrotate(x);
  99. erase(x, v);
  100. }
  101. } else if (tree[x].val < v) {
  102. erase(tree[x].rson, v);
  103. update(x);
  104. } else if (tree[x].val > v) {
  105. erase(tree[x].lson, v);
  106. update(x);
  107. }
  108. }
  109. ull getsum(ul x, ull t)
  110. {
  111. if (!x) {
  112. return 0;
  113. }
  114. if (tree[x].val > t) {
  115. return getsum(tree[x].lson, t);
  116. } else if (tree[x].val == t) {
  117. return tree[x].sum - tree[tree[x].rson].sum;
  118. } else if (tree[x].val < t) {
  119. return tree[x].sum - tree[tree[x].rson].sum + getsum(tree[x].rson, t);
  120. }
  121. }
  122. const ul sz = 1 << 18;
  123. ul a[sz];
  124. ul heads[sz << 1];
  125. void seginsert(ul pos, ul v)
  126. {
  127. for (pos |= sz; pos; pos >>= 1) {
  128. insert(heads[pos], v);
  129. }
  130. }
  131. void segerase(ul pos, ul v)
  132. {
  133. for (pos |= sz; pos; pos >>= 1) {
  134. erase(heads[pos], v);
  135. }
  136. }
  137. ull getsum(ul l, ul r, ull t)
  138. {
  139. ull ret = 0;
  140. for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {
  141. if (~l & 1) {
  142. ret += getsum(heads[l ^ 1], t);
  143. }
  144. if (r & 1) {
  145. ret += getsum(heads[r ^ 1], t);
  146. }
  147. }
  148. return ret;
  149. }
  150. int main()
  151. {
  152. rnd.seed(std::time(0));
  153. std::scanf("%u%u", &n, &q);
  154. for (ul i = 1; i <= n; ++i) {
  155. std::scanf("%u", &a[i]);
  156. seginsert(i, a[i]);
  157. }
  158. for (ul i = 1; i <= q; ++i) {
  159. ul qt;
  160. std::scanf("%u", &qt);
  161. if (qt == 1) {
  162. ul x, y;
  163. std::scanf("%u%u", &x, &y);
  164. segerase(x, a[x]);
  165. a[x] = y;
  166. seginsert(x, y);
  167. } else if (qt == 2) {
  168. ul l, r;
  169. std::scanf("%u%u", &l, &r);
  170. ull t = 1;
  171. while (true) {
  172. ull newt = getsum(l, r, t) + 1;
  173. if (newt == t) {
  174. break;
  175. }
  176. t = newt;
  177. }
  178. std::printf("%llu\n", t);
  179. }
  180. }
  181. return 0;
  182. }

I、Interesting game

感觉这是个需要很麻烦分类讨论的题,搁置。

J、Loli, Yen-Jen, and a graph problem

参考https://www.zybuluo.com/qq290637843/note/1776933中的情况一。

  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. ul n;
  10. ul f(ul x, ul y, ul n)
  11. {
  12. return x + y <= n - 1 ? x + y : x + y - n + 1;
  13. }
  14. ul g(ul x, ul n)
  15. {
  16. return x + x <= n - 1 ? n - x : n + 1 - x;
  17. }
  18. const ul maxn = 1000;
  19. std::vector<ul> roads[(maxn >> 1) + 1];
  20. int main()
  21. {
  22. std::scanf("%u", &n);
  23. if (n & 1) {
  24. for (ul i = 1; i <= ((n - 1) >> 1); ++i) {
  25. roads[i].push_back(n);
  26. roads[i].push_back(f(1, i - 1, n));
  27. for (ul j = 1, gj1 = g(1, n); j <= n - 2; ++j, gj1 = g(gj1, n)) {
  28. roads[i].push_back(f(gj1, i - 1, n));
  29. }
  30. roads[i].push_back(n);
  31. }
  32. for (ul i = 1; i <= n - 1; ++i) {
  33. if (i + i <= n - 1) {
  34. for (ul j = 0; j <= i; ++j) {
  35. if (j) {
  36. std::putchar(' ');
  37. }
  38. std::printf("%u", roads[i][j]);
  39. }
  40. std::putchar('\n');
  41. } else {
  42. for (ul j = n - i; j <= n; ++j) {
  43. if (j != n - i) {
  44. std::putchar(' ');
  45. }
  46. std::printf("%u", roads[n - i][j]);
  47. }
  48. std::putchar('\n');
  49. }
  50. }
  51. } else {
  52. for (ul i = 1; i <= (n >> 1); ++i) {
  53. roads[i].push_back(f(1, i - 1, n + 1));
  54. for (ul j = 1, gj1 = g(1, n + 1); j <= n - 1; ++j, gj1 = g(gj1, n + 1)) {
  55. roads[i].push_back(f(gj1, i - 1, n + 1));
  56. }
  57. }
  58. for (ul i = 1; i <= n - 1; ++i) {
  59. if (i + i <= n - 2) {
  60. for (ul j = 0; j <= i; ++j) {
  61. if (j) {
  62. std::putchar(' ');
  63. }
  64. std::printf("%u", roads[i][j]);
  65. }
  66. std::putchar('\n');
  67. } else if (i <= n - 2) {
  68. for (ul j = n - 1 - i; j <= n - 1; ++j) {
  69. if (j != n - 1 - i) {
  70. std::putchar(' ');
  71. }
  72. std::printf("%u", roads[n - 1 - i][j]);
  73. }
  74. std::putchar('\n');
  75. } else {
  76. for (ul j = 0; j <= n - 1; ++j) {
  77. if (j) {
  78. std::putchar(' ');
  79. }
  80. std::printf("%u", roads[n >> 1][j]);
  81. }
  82. std::putchar('\n');
  83. }
  84. }
  85. }
  86. return 0;
  87. }

K、K-rectangle

表示解决的覆盖问题所需最小花费,那么显然满足如下递推式:

注意对于固定的关于构成一不增函数,且会构成一些相等的段,现在考虑其中一段,记其值为,那么在该段当中,假设,那么优于当且仅当:
故对于该段中可以使用斜率优化,且斜率只和有关而与处其他信息无关。并且注意到,随增大,关于构成的相等段只会发生合并而不会发生分裂,所以只需要维护一个“逐渐合并的分段凸壳”,并维护出每个分段的最优即可。
现在考虑怎么从这些分段中选出最优分段。考虑两个分段(注意是递减的),其对应,那么优于当且仅当:
故对于最优段的选取又可以使用斜率优化,但是要注意一个问题,内层的斜率优化过程只有凸壳合并,但外层的斜率优化有从后缀删点过程,这意味着原先不在凸壳上的某些点可能会因为从后缀删点而浮到凸壳上,所以外层的斜率优化要树上斜率优化。

  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 pulll = std::pair<ul, ll>;
  10. ul n;
  11. const ul maxn = 4e5;
  12. ll k;
  13. ll x[maxn + 1];
  14. ll y[maxn + 1];
  15. ll f[maxn + 1];
  16. class data1 {
  17. public:
  18. ul prev = 0;
  19. ul next = 0;
  20. ll x = 0;
  21. ll f = 0;
  22. };
  23. ul tot = 0;
  24. data1 point1[maxn + 1];
  25. class edge_t {
  26. public:
  27. ul to = 0;
  28. ul nex = 0;
  29. };
  30. edge_t edge[maxn + maxn + 1];
  31. ul totedge;
  32. ul head[maxn + 1];
  33. ul rhead[maxn + 1];
  34. ul rank[maxn + 1];
  35. void addedge(ul a, ul b)
  36. {
  37. ++totedge;
  38. if (!head[a]) {
  39. head[a] = totedge;
  40. }
  41. edge[totedge].to = b;
  42. if (rhead[a]) {
  43. edge[rhead[a]].nex = totedge;
  44. }
  45. rhead[a] = totedge;
  46. }
  47. ul fa[maxn + 1];
  48. std::vector<pulll> stack;
  49. void getcen(ul curr, ul prev, ul totsz, ul& sz, ul& mnmxsz, ul& mnmxsznid)
  50. {
  51. sz = 1;
  52. ul mxsz = 0;
  53. for (ul eid = head[curr]; eid; eid = edge[eid].nex) {
  54. ul nex = edge[eid].to;
  55. if (rank[nex]) {
  56. continue;
  57. }
  58. if (nex == prev) {
  59. continue;
  60. }
  61. ul sonsz;
  62. getcen(nex, curr, totsz, sonsz, mnmxsz, mnmxsznid);
  63. mxsz = std::max(mxsz, sonsz);
  64. sz += sonsz;
  65. }
  66. mxsz = std::max(mxsz, totsz - sz);
  67. if (mnmxsz > mxsz) {
  68. mnmxsz = mxsz;
  69. mnmxsznid = curr;
  70. }
  71. }
  72. void getsz(ul curr, ul prev, ul& sz)
  73. {
  74. sz = 1;
  75. for (ul eid = head[curr]; eid; eid = edge[eid].nex) {
  76. ul nex = edge[eid].to;
  77. if (rank[nex]) {
  78. continue;
  79. }
  80. if (nex == prev) {
  81. continue;
  82. }
  83. ul sonsz;
  84. getsz(nex, curr, sonsz);
  85. sz += sonsz;
  86. }
  87. }
  88. class hull1 {
  89. public:
  90. ul left = 0;
  91. ul right = 0;
  92. ul ptr = 0;
  93. ll y = 0;
  94. void pop_back() {
  95. if (ptr == right) {
  96. ptr = point1[right].prev;
  97. }
  98. right = point1[right].prev;
  99. point1[right].next = 0;
  100. }
  101. void pop_front() {
  102. if (ptr == left) {
  103. ptr = point1[left].next;
  104. }
  105. left = point1[left].next;
  106. point1[left].prev = 0;
  107. }
  108. };
  109. std::vector<hull1> hulls;
  110. class data2 {
  111. public:
  112. ll y = 0;
  113. ll fmxy = 0;
  114. };
  115. data2 point2[maxn + 1];
  116. bool check(const data1& a, const data1& b, const data1& c)
  117. {
  118. return (b.f - a.f) * (c.x - b.x) >= (c.f - b.f) * (b.x - a.x);
  119. }
  120. bool check(const data2& a, const data2& b, const data2& c)
  121. {
  122. return (b.fmxy - a.fmxy) * (c.y - b.y) >= (c.fmxy - b.fmxy) * (b.y - a.y);
  123. }
  124. void merge(hull1& a, hull1& b)
  125. {
  126. ll y = b.y;
  127. while (true) {
  128. if (point1[a.right].prev && check(point1[point1[a.right].prev], point1[a.right], point1[b.left])) {
  129. a.pop_back();
  130. } else if (point1[b.left].next && check(point1[a.right], point1[b.left], point1[point1[b.left].next])) {
  131. b.pop_front();
  132. } else {
  133. break;
  134. }
  135. }
  136. bool flag = b.left == b.ptr;
  137. point1[a.right].next = b.left;
  138. point1[b.left].prev = a.right;
  139. b.left = a.left;
  140. if (flag) {
  141. b.ptr = a.ptr;
  142. while (point1[b.ptr].next && point1[point1[b.ptr].next].f - point1[b.ptr].f < y * (point1[point1[b.ptr].next].x - point1[b.ptr].x)) {
  143. b.ptr = point1[b.ptr].next;
  144. }
  145. }
  146. }
  147. std::vector<data2> hull2;
  148. ul it;
  149. void search(ul curr, ul rk)
  150. {
  151. while (it && hull2[it].fmxy - hull2[it - 1].fmxy > (hull2[it].y - hull2[it - 1].y) * (-x[curr] - k)) {
  152. --it;
  153. }
  154. f[curr] = std::min(f[curr], hull2[it].y * (x[curr] + k) + hull2[it].fmxy);
  155. for (ul eid = head[curr]; eid; eid = edge[eid].nex) {
  156. ul next = edge[eid].to;
  157. if (next < curr) {
  158. continue;
  159. }
  160. if (rank[next] > rk) {
  161. continue;
  162. }
  163. search(next, rk);
  164. }
  165. }
  166. int main()
  167. {
  168. std::scanf("%u%lld", &n, &k);
  169. for (ul i = 1; i <= n; ++i) {
  170. std::scanf("%lld%lld", &x[i], &y[i]);
  171. }
  172. stack.push_back(pulll(0, 1e9));
  173. for (ul i = 1; i <= n; ++i) {
  174. while (stack.back().second <= y[i]) {
  175. stack.pop_back();
  176. }
  177. fa[i] = stack.back().first;
  178. stack.push_back(pulll(i, y[i]));
  179. addedge(i, fa[i]);
  180. addedge(fa[i], i);
  181. }
  182. for (ul i = 0; i <= n; ++i) {
  183. while (!rank[i]) {
  184. ul sz;
  185. getsz(i, 0, sz);
  186. ul mnmxsz = sz, mnmxsznid;
  187. getcen(i, -1, sz, sz, mnmxsz, mnmxsznid);
  188. rank[mnmxsznid] = sz;
  189. }
  190. }
  191. for (ul i = 1; i <= n; ++i) {
  192. f[i] = 3e12;
  193. }
  194. for (ul i = 1; i <= n; ++i) {
  195. hull1 tmp;
  196. ++tot;
  197. tmp.left = tot;
  198. tmp.right = tot;
  199. tmp.y = y[i];
  200. tmp.ptr = tot;
  201. point1[tot].x = x[i];
  202. point1[tot].f = f[i - 1];
  203. while (hulls.size() && hulls.back().y <= y[i]) {
  204. merge(hulls.back(), tmp);
  205. hulls.pop_back();
  206. }
  207. hulls.push_back(tmp);
  208. point2[i].y = y[i];
  209. point2[i].fmxy = point1[tmp.ptr].f - point1[tmp.ptr].x * y[i];
  210. hull2.resize(0);
  211. for (ul j = i; j && rank[j] <= rank[i]; j = fa[j]) {
  212. while (hull2.size() >= 2 && check(hull2[hull2.size() - 2], hull2.back(), point2[j])) {
  213. hull2.pop_back();
  214. }
  215. hull2.push_back(point2[j]);
  216. }
  217. it = hull2.size() - 1;
  218. search(i, rank[i]);
  219. }
  220. std::printf("%lld\n", f[n]);
  221. return 0;
  222. }

L、Loli, Yen-Jen, and a cool problem

字典树的后缀自动机

  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. class sam_t {
  10. public:
  11. ul las;
  12. class node {
  13. public:
  14. ul ch[26];
  15. ul len = 0;
  16. ul fa = 0;
  17. node() {
  18. std::memset(ch, 0, sizeof(ch));
  19. }
  20. };
  21. std::vector<node> st = std::vector<node>(1e6);
  22. void add(ul c)
  23. {
  24. ul p = las;
  25. if (st[p].ch[c]) {
  26. las = st[p].ch[c];
  27. return;
  28. }
  29. ul np = las = st.size();
  30. st.push_back(node());
  31. st[np].len = st[p].len + 1;
  32. for ( ; p && !st[p].ch[c]; p = st[p].fa) {
  33. st[p].ch[c] = np;
  34. }
  35. if (!p) {
  36. st[np].fa = 1;
  37. } else {
  38. ul q = st[p].ch[c];
  39. if (st[q].len == st[p].len + 1) {
  40. st[np].fa = q;
  41. } else {
  42. ul nq = st.size();
  43. st.push_back(node());
  44. st[nq] = st[q];
  45. st[nq].len = st[p].len + 1;
  46. st[q].fa = st[np].fa = nq;
  47. for ( ; p && st[p].ch[c] == q; p = st[p].fa) {
  48. st[p].ch[c] = nq;
  49. }
  50. }
  51. }
  52. }
  53. void init() {
  54. las = 1;
  55. st.resize(0);
  56. st.resize(2);
  57. }
  58. };
  59. sam_t sam;
  60. const ul maxn = 3e5;
  61. ul n;
  62. ul q;
  63. char s[maxn + 2];
  64. std::vector<ul> sons[maxn + 1];
  65. ul las[maxn + 1];
  66. std::deque<std::pair<ul, ul>> queue;
  67. ul fa[ul(1e6)][20];
  68. ul cnt[ul(1e6)];
  69. std::vector<ul> sons2[ul(1e6)];
  70. ul depth[ul(1e6)];
  71. void search(ul curr)
  72. {
  73. for (ul t = 1; (1 << t) <= depth[curr]; ++t) {
  74. fa[curr][t] = fa[fa[curr][t - 1]][t - 1];
  75. }
  76. for (ul next : sons2[curr]) {
  77. fa[next][0] = curr;
  78. depth[next] = depth[curr] + 1;
  79. search(next);
  80. cnt[curr] += cnt[next];
  81. }
  82. }
  83. int main()
  84. {
  85. std::scanf("%u%u", &n, &q);
  86. std::scanf("%s", s + 1);
  87. for (ul i = 2; i <= n; ++i) {
  88. ul f;
  89. std::scanf("%u", &f);
  90. sons[f].push_back(i);
  91. }
  92. sam.init();
  93. queue.push_back(std::pair<ul, ul>(0, 1));
  94. las[0] = 1;
  95. while (queue.size()) {
  96. auto curr = queue.front();
  97. queue.pop_front();
  98. sam.las = las[curr.first];
  99. sam.add(s[curr.second] - 'A');
  100. las[curr.second] = sam.las;
  101. curr.first = curr.second;
  102. for (ul next : sons[curr.first]) {
  103. curr.second = next;
  104. queue.push_back(curr);
  105. }
  106. }
  107. for (ul i = 2; i != sam.st.size(); ++i) {
  108. sons2[sam.st[i].fa].push_back(i);
  109. }
  110. for (ul i = 1; i <= n; ++i) {
  111. ++cnt[las[i]];
  112. }
  113. search(1);
  114. for (ul i = 1; i <= q; ++i) {
  115. ul x, l;
  116. std::scanf("%u%u", &x, &l);
  117. x = las[x];
  118. for (ul t = 31 - __builtin_clz(depth[x]); ~t; --t) {
  119. if (depth[x] >= (1 << t) && sam.st[fa[x][t]].len >= l) {
  120. x = fa[x][t];
  121. }
  122. }
  123. std::printf("%u\n", cnt[x]);
  124. }
  125. return 0;
  126. }

M、Kill the tree

对每个子树求重心。

  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. ul n;
  10. const ul maxn = 2e5;
  11. std::vector<ul> edges[maxn + 1];
  12. ul sz[maxn + 1];
  13. ul cen[maxn + 1];
  14. ul fa[maxn + 1];
  15. ul type[maxn + 1];
  16. void search(ul curr, ul prev)
  17. {
  18. sz[curr] = 1;
  19. cen[curr] = curr;
  20. for (ul next : edges[curr]) {
  21. if (next == prev) {
  22. continue;
  23. }
  24. fa[next] = curr;
  25. search(next, curr);
  26. if (sz[curr] <= sz[next]) {
  27. cen[curr] = cen[next];
  28. }
  29. sz[curr] += sz[next];
  30. while (sz[curr] - sz[cen[curr]] > sz[cen[curr]]) {
  31. cen[curr] = fa[cen[curr]];
  32. }
  33. }
  34. if (sz[curr] - sz[cen[curr]] == sz[cen[curr]]) {
  35. type[curr] = 2;
  36. } else {
  37. type[curr] = 1;
  38. }
  39. }
  40. int main()
  41. {
  42. std::scanf("%u", &n);
  43. for (ul i = 1; i <= n - 1; ++i) {
  44. ul a, b;
  45. std::scanf("%u%u", &a, &b);
  46. edges[a].push_back(b);
  47. edges[b].push_back(a);
  48. }
  49. search(1, 0);
  50. for (ul i = 1; i <= n; ++i) {
  51. if (type[i] == 2) {
  52. std::printf("%u %u\n", std::min(cen[i], fa[cen[i]]), std::max(cen[i], fa[cen[i]]));
  53. } else {
  54. std::printf("%u\n", cen[i]);
  55. }
  56. }
  57. return 0;
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注