我们就让甲先行动一步,则会产生先拿 a a a 和先拿 b b b 两种结果。这样问题就转化成了总数为 n − a n - a n−a 或者 n − b n - b n−b,乙先手问后手是否必败。我们令 f i f_i fi 表示石子数位 i i i 时先手是否必胜,则有:
f i = 1 − ( f i − a ∨ f i − b ) f_i = 1 - (f_{i - a} \lor f_{i - b}) fi=1−(fi−a∨fi−b)
这样直接递推显然不行,所以我们考虑找找规律。打表发现 f f f 时循环的,所以我们考虑证明 f f f 循环的性质(循环节时 a + b a + b a+b)。
这个循环其实也挺显然的,要证循环那么就是证明 f a + b + i = f i f_{a + b + i} = f_i fa+b+i=fi,那么分两种情况,如果 f i = 0 f_i = 0 fi=0,那么后手必胜,那么在局面为 a + b + i a + b + i a+b+i 的时候只要乙和甲拿相反的东西就能让局面回到 f i f_i fi,于是还是后手必胜: f a + b + i = f i = 0 f_{a + b + i} = f_i = 0 fa+b+i=fi=0。 f i = 1 f_i = 1 fi=1 的情况同理。
于是我们可以在最开始把 n n n 模上 a + b a + b a+b,然后再进行处理(下文的 n n n 都是进行过取模操作之后的 n n n)。
我们不妨设 a > b a > b a>b,在我们会发现,先手必胜的条件首先一个先显然的就是 n > max ( a , b ) = a n > \max(a, b) = a n>max(a,b)=a,因为先手可以拿走 a a a,又因为 n ∈ [ a , a + b ) n \in [a, a + b) n∈[a,a+b),所以剩下的数等于 n − a ∈ [ 0 , b ) n - a \in [0, b) n−a∈[0,b),所以乙就不可能拿走任何东西了。
所以,条件一: n ∈ [ a , a + b ) n \in [a, a + b) n∈[a,a+b)。
还有一个条件是 n ∈ [ b , 2 b ) ∪ [ 3 b , 4 b ) ∪ [ 5 b , 6 b ) ∪ ⋯ n \in [b, 2b) \cup [3b, 4b) \cup [5b, 6b) \cup \cdots n∈[b,2b)∪[3b,4b)∪[5b,6b)∪⋯,也就是 n ∈ [ ( 2 k − 1 ) b , 2 k b ) , k ∈ N ∗ n \in [(2k-1)b, 2kb), k \in N^* n∈[(2k−1)b,2kb),k∈N∗,因为此时 n < a n < a n<a,所以双方都只能拿 b b b,所以只要是奇数个 b b b 就一定是先手赢。
所以第二个条件 ⌊ n b ⌋ m o d 2 = 1 \lfloor\frac n b\rfloor \mod 2 = 1 ⌊bn⌋mod2=1
这样就是 O ( 1 ) O(1) O(1) 判断,然后我们就可以 O ( T ) O(T) O(T) 解决问题了。
考试的时候写的二分答案,结果 W A WA WA 了,二分答案的正确性不能保证:
h a c k hack hack: 100 , 90 , 84 , 55 , 47 , 44 , 41 , 41 , 30 , 30 , 5 100, 90, 84, 55, 47, 44, 41, 41, 30, 30, 5 100,90,84,55,47,44,41,41,30,30,5
w = 189 w = 189 w=189 的时候第一次 100 + 84 + 5 = 189 100 + 84 + 5 = 189 100+84+5=189,第二次 90 + 55 + 44 = 189 90 + 55 + 44 = 189 90+55+44=189,第三次 47 + 41 + 41 + 30 + 30 = 189 47 + 41 + 41 + 30 + 30 = 189 47+41+41+30+30=189。
w = 190 w = 190 w=190 的时候第一次 100 + 90 = 190 100 + 90 = 190 100+90=190,第二次 84 + 55 + 47 = 186 84 + 55 + 47 = 186 84+55+47=186,第三次 44 + 41 + 41 + 30 + 30 = 186 44 + 41 + 41 + 30 + 30 = 186 44+41+41+30+30=186,第四次 5 5 5。
这样就不是单增的了,所以二分答案的正确性无法保证。但是为什么是错的呢,是因为每次装是贪心的装而不是 d p dp dp(背包)的装法,所以会首先把大的放进去,导致下一次有小的放不进去,会浪费空间。
虽然不能直接二分答案,但是我们可以找到替代方案,我们可以证明对于 A = max i = 1 n a i A = \max\limits_{i = 1}^n a_i A=i=1maxnai, w + A w + A w+A 一定比 w w w 更优。因为在这种情况下,每一条船所装的袋数均不会下降。
所以我们可以在二分答案过后再暴力验证答案周围的 A A A 个位置来确保是正确的。
不知道为什么今天有两道循环的题。
看这个数据范围 k ≤ 1 e 9 k \leq 1e9 k≤1e9,似乎也没有什么算法能 hold 的注这个数据范围(除了一些 O ( log n ) O(\log n) O(logn) 的小算法),所以我们还是打表找规律。
我们发现其中有 20 p t s 20pts 20pts 是 n = 1 n = 1 n=1 的时候,所以我们稍微手算几个自己造的样例就会发现 n = 1 n = 1 n=1 的时候是会循环的,就比如:
4 → 3 , 1 → 2 , 2 → 2 , 1 , 1 → 3 , 1 → ⋯ 4 \to 3, 1 \to 2, 2 \to 2, 1, 1 \to 3, 1 \to \cdots 4→3,1→2,2→2,1,1→3,1→⋯
所以我们考虑证明循环的正确性:
因为石子个数有限,并且产生的所有情况下石子数量和都是固定的数字。又因为显然任意一个数字 m m m 的拆分数是有限的,所以情况数是有限的。所以只要 k k k 足够大,我们就必定会回到以前出现过的情况,也就会产生循环。
现在的问题就在于循环节,如果循环节不是很长的话就可以直接打表了。
然后就要证明循环节长度,但是 T J TJ TJ 的证明是势能分析,然后我也没看懂,所以就不证了吧qwq。具体来说就是先要操作 S = ∑ i = 1 n a i S = \sum\limits_{i = 1}^n a_i S=i=1∑nai 次进入循环节,然后循环节是 m x = max i = 1 n ( i + a i ) − 1 mx = \max\limits_{i = 1}^n (i + a_i) - 1 mx=i=1maxn(i+ai)−1。
考场上暴力都不会打…