WC 2026

· · 生活·游记

Part 0

[Current Time: 08:00]
Login: AH-004
Password: xkjegh
-----------------------
C139:~/AH-004/#

Part 1

打开 T1,这个数据范围好神秘啊!

先写出一个正确做法:

[Current Time: 08:10]
C139:~/AH-004/binary# cp template_binary.cpp binary.cpp
binary(x, y):
  ans := inf
  for i in 1..60:
    if x * 2^i > y then break
    ans [min]:= i + (y - x * 2^i) / 2^i + popcount(y mod 2^i)
  return ans
[Current Time: 08:20]
[Self Evalution #1]
...
Test 6: Accepted (0.0 s)
Test 7: Wrong Answer (0.0 s)
...
-----------------------
Score: 24 / 100

啊?看来做法是错的。

再来:

binary(x, y):
  ans := inf
  for i in 1..60:
    if x * 2^i > y then break
    for j in 0..i:
      ans [min]:= i + j + (y + j - x * 2^i) / 2^i + popcount((y + j) mod 2^i)
  return ans
[Current Time: 08:30]
[Self Evalution #4]
...
Test 16: Accepted (1.6 s)
Test 17: Time Limit Exceeded (> 4.0 s)
...
-----------------------
Score: 64 / 100

总算没有 WA 了,但 64 分看上去很烂啊!

试试优化:

binary(x, y):
  ans := inf
  for i in 1..60:
    if x * 2^i > y then break
    j := 0
    while j <= i:
      ans [min]:= i + j + (y + j - x * 2^i) / 2^i + popcount((y + j) mod 2^i)
      j := j + lowbit(j)
  return ans
[Current Time: 08:40]
[Self Evalution #5]
...
Test 21: Accepted (0.3 s)
Test 22: Time Limit Exceeded (3.2 s)
Test 23: Time Limit Exceeded (3.2 s)
Test 24: Time Limit Exceeded (> 4.0 s)
Test 25: Time Limit Exceeded (> 4.0 s)
-----------------------
Score: 84 / 100
# Part 2 对于 T2,首先把 $x - t$ 图画出来……在进一步思考前写个离散化吧。 ```plain [Current Time: 08:50] C139:~/AH-004/game# cp template_game.cpp game.cpp ``` ```cpp game(n, m, k, mice): segments := [] for mouse in mice: segments := segments + convert(mouse) segments.coordinates.discretize(index=1) p, q := segments.coordinates.max // To be completed return -1 ``` ```plain [Current Time: 09:20] C139:~/AH-004/game# cp game.cpp game.cpp.save ``` 那么旋转 $45$ 度得到了: - $a < b$:得到线段 $(t + a, t - a + m) - (t + 2b - a, t - a + m)$。 - $a > b$:得到线段 $(t + a, t - a + m) - (t + a, t - 2b + a + m)$。 - $a = 0$ 时,向横轴负方向无限延伸线段。 - $a = m$ 时,向纵轴负方向无限延伸线段。 - $b = 0$ 时,向横轴正方向无限延伸线段。 - $b = m$ 时,向纵轴正方向无限延伸线段。 - 需要从 $(0, 0)$ 向右或向下走到 $(2 \times 10^9, 2 \times 10^9)$ 并让它必须穿过至少 $k$ 个线段。 对于特殊性质 C,只需要判断答案是否为 $-1$,离散化后得到了 $O(n^2)$ 做法。 那么开始写吧! ```plain [Current Time: 09:30] C139:~/AH-004/game# cp game.cpp.save game.cpp ``` ```cpp game(n, m, k, mice): ... dp := [inf] dp[1][1] := 0 horizonal, vertical := [[0]] for segment in segments: if segment.horizonal then: for i in (segment.left.x)..(segment.right.x - 1): horizonal[i][segment.y] := horizonal[i][segment.y] + 1 if segment.vertical then: for i in (segment.left.y)..(segment.right.y - 1): vertical[segment.x][i] := vertical[segment.x][i] + 1 for i in 1..p: for j in 1..q: dp[i][j] := min(dp[i][j - 1] + vertical[i][j], dp[i - 1][j] + horizonal[i][j]) if dp[p][q] <= k then return -1 return 0 ``` ```plain [Current Time: 10:00] C139:~/AH-004/game# g++ grader.cpp game.cpp -o -O2 -std=c++14 -static C139:~/AH-004/game# ./game < game3.in 0 -1 -1 0 -1 -1 -1 -1 C139:~/AH-004/game# cat game3.ans 0 -1 -1 0 -1 0 -1 0 ``` 嗯?……原来是血量扣减到 $0$ 也算达成目标。 ```cpp game(n, m, k, mice): ... if dp[p][q] <= k - 1 then return -1 return 0 ``` ```plain [Current Time: 10:10] C139:~/AH-004/game# g++ grader.cpp game.cpp -o -O2 -std=c++14 -static C139:~/AH-004/game# ./game < game3.in 0 -1 -1 0 -1 0 -1 0 C139:~/AH-004/game# cat game3.ans 0 -1 -1 0 -1 0 -1 0 ``` ```plain [Current Time: 10:20] [Self Evalution #9] Test 1: Wrong Answer Test 2: Wrong Answer Test 3: Accepted Test 4: Accepted Test 5: Runtime Error Test 6: Runtime Error Test 7: Accepted Test 8: Accepted Test 9: Runtime Error ... ----------------------- Score: 16 / 100 ``` 啊!接下来对于暴力分 $O(2^k)$ 枚举选择的线段就好了。 ```cpp partial_game(p, q, segments): ... if dp[p][q] <= k - 1 then return FALSE return TRUE game(n, m, k, mice): ... if n <= 10: for S in segments.subsets: W = S.w.sum if partial_game(p, q, S) then ans [min]:= W if ans = inf then return -1 return ans ... ``` ```plain [Current Time: 10:30] [Self Evalution #10] Test 1: Accepted Test 2: Accepted Test 3: Accepted Test 4: Accepted Test 5: Runtime Error Test 6: Runtime Error Test 7: Accepted Test 8: Accepted Test 9: Runtime Error ... ----------------------- Score: 24 / 100 ``` # Part 3 T1 中那个 $i$ 的枚举看上去很慢啊!试试优化: ```cpp pp := [] t := 32768 self_popcount_init(): for i in 0..(t - 1): pp[i] := popcount(i) self_popcount(x): if x <= t - 1 then return pp[x] return pp[x mod t] + pp[x / t mod t] + pp[x / t^2 mod t] + pp[x / t^3 mod t] init(): self_popcount_init() binary(x, y): ans := inf for i in (log2(y / x) - 1)..60: if x * 2^i > y then break j := 0 while j <= i: ans [min]:= i + j + (y + j - x * 2^i) / 2^i + self_popcount((y + j) mod 2^i) j := j + lowbit(j) return ans ``` ```plain [Current Time: 10:40] [Self Evalution #11] ... Test 21: Accepted (0.1 s) Test 22: Accepted (2.8 s) Test 23: Accepted (2.8 s) Test 24: Time Limit Exceeded (> 4.0 s) Test 25: Time Limit Exceeded (> 4.0 s) ----------------------- Score: 92 / 100 ``` $92$ 分……?这个分数这么这么奇怪。 但这个 Test 24 纹丝不动啊!去看 T3 了。 # Part 4 那么我们有一个最暴力的想法:在 $2, 3, \ldots, n$ 号结点各放两对铅笔橡皮,第一对将树改为菊花,第二对达成目标。 ```cpp dfs1(tree, now, father): for x in tree.neighbours(now): if x != father then dfs1(tree, x, now) if now != 1 then alter(now - 1, 1, father) dfs2(tree, now, father): if now != 1 then alter(n - 1 + now - 1, father, 1) for x in tree.neighbours(now): if x != father then dfs1(tree, x, now) paint(n, T1, T2): setting(2 * n - 2, [2, 3, ..., n, 2, 3, ..., n]) dfs1(T1, 1, 0) dfs2(T2, 1, 0) ``` ```plain [Current Time: 11:00] [Self Evalution #16] ... Test 1: Accepted (14 / 14 points) Test 2: Accepted (23 / 23 points) Test 3: Partially Correct (1 / 26 points) Test 4: Wrong Answer (0 / 37 points) ----------------------- Score: 38 / 100 ``` # Part 5 ```plain [Current Time: 13:00] [Self Evalution #21] <Task "binary"> ... Score: 92 / 100 <Task "game"> ... Score: 24 / 100 <Task "binary"> ... Score: 38 / 100 ``` ???后面 2h 我什么也没做,于是比赛结束了。 # Part 6 ```plain [Current Time: 15:00] Login: AH-004 Password: xkjegh ----------------------- [Final Evalution] binary: 92 / 100 game: 24 / 100 paint: 38 / 100 ----------------------- Total Score: 154 / 300 ```