标签:max ash isp 方式 problem code std fine def
显然对每一堆石子求一个SG之后异或起来就好了。
这个SG看起来只能\(O(n^2)\)的样子啊,考虑找规律;
一下是\(k=3\)时的一些SG函数的值
SG(1): 0 SG(2): 0 SG(3): 1
SG(4): 0 SG(5): 1 SG(6): 2
SG(7): 0 SG(8): 1 SG(9): 3
SG(10): 2 SG(11): 0 SG(12): 4
SG(13): 1 SG(14): 3 SG(15): 5
SG(16): 2 SG(17): 0 SG(18): 6
SG(19): 4 SG(20): 1 SG(21): 7
SG(22): 3 SG(23): 5 SG(24): 8
SG(25): 2 SG(26): 0 SG(27): 9
SG(28): 6 SG(29): 4 SG(30): 10
SG(31): 1 SG(32): 7 SG(33): 11
SG(34): 3 SG(35): 5 SG(36): 12
SG(37): 8 SG(38): 2 SG(39): 13
SG(40): 0 SG(41): 9 SG(42): 14
SG(43): 6 SG(44): 4 SG(45): 15
SG(46): 10 SG(47): 1 SG(48): 16
SG(49): 7 SG(50): 11 SG(51): 17
不难发现一些规律
\[ \operatorname{SG}(n) = \begin{cases} 0 & 0 \le n < k \\ \frac{n}{k} & n \bmod k = 0 \\ \displaystyle \operatorname{SG} \!\left(n - \!\left\lfloor \frac{n}{k} \right\rfloor\! - 1 \right) & n \bmod k !\neq 0 \end{cases} \]
我们发现直接那这个式子来暴力算复杂度还是\(O(n)\)的,考虑在转移的过程中把\(\left\lfloor \frac{n}{k} \right\rfloor\)相等的转移一起做;
设\(x=\lfloor \frac{n}{k} \rfloor\),则我们需要找到一个最大的\(y\)满足\(n-y(x+1)\geq x\times k\),即\(y=\lfloor \frac{n-x\times k}{x+1}\rfloor\),这中间的转移\(\lfloor \frac{n}{k} \rfloor\)是不变的,于是我们可以直接令\({\rm SG}(n)={\rm SG}(n-(x+1)y)\);
考虑复杂度,当\(k\leq \sqrt{n}\)时,\(\left\lfloor \frac{n}{k} \right\rfloor>\sqrt{n}\),于是每次\(n\)都会至少减去\(\sqrt{n}\),于是这边复杂度是\(O(\sqrt{n})\)的;当\(k>\sqrt{n}\)时,\(\left\lfloor \frac{n}{k} \right\rfloor\leq \sqrt{n}\),按照上面的转移方式每进行一次转移\(\left\lfloor \frac{n}{k} \right\rfloor\)的值至少会减少\(1\),于是复杂度也是\(O(\sqrt{n})\)的。
代码
#include<bits/stdc++.h>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int T,n,m;
int bf(int n) {
if(n<m) return 0;if(n%m==0) return n/m;
return bf(n-n/m-1);
}
int sg(int n) {
if(n<m) return 0;if(n%m==0) return n/m;
int x=n/m;int u=x*m;
int h=(n-u)/(x+1);
if(n-h*(x+1)==u) return x;
return sg(n-(h+1)*(x+1));
}
int main() {
int ans=0;
for(re int T=read();T;--T) {
n=read(),m=read();
if(m<=n/m) ans^=bf(n);
else ans^=sg(n);
}
if(ans) puts("Takahashi");
else puts("Aoki");
return 0;
}
标签:max ash isp 方式 problem code std fine def
原文地址:https://www.cnblogs.com/asuldb/p/12334280.html