显然是算SG函数。
打个表出来,会发现
S
G
(
n
,
k
)
SG(n,k)
SG(n,k)当
n
m
o
d
k
=
0
n\bmod k=0
nmodk=0时为
n
/
k
n/k
n/k,不过其他情况下似乎不能直接
O
(
1
)
\mathcal O(1)
O(1)得出。
仔细分析一波,容易归纳证明
S
G
(
n
−
⌊
n
k
⌋
,
k
)
SG(n- \lfloor \frac{n}{k} \rfloor,k)
SG(n−⌊kn⌋,k)到
S
G
(
n
,
k
)
SG(n,k)
SG(n,k)互不相同且取遍
0
0
0~
⌊
n
k
⌋
\lfloor \frac{n}{k} \rfloor
⌊kn⌋之间整数。于是当
n
m
o
d
k
≠
0
n \bmod k \neq 0
nmodk=0时有
S
G
(
n
,
k
)
=
S
G
(
n
−
⌊
n
k
⌋
−
1
,
k
)
SG(n,k)=SG(n-\lfloor \frac{n}{k} \rfloor-1,k)
SG(n,k)=SG(n−⌊kn⌋−1,k)。这样精细实现一下容易做到
O
(
min
(
k
log
n
,
⌊
n
k
⌋
)
)
\mathcal O(\min(k\log n,\lfloor \frac{n}{k} \rfloor))
O(min(klogn,⌊kn⌋))计算
S
G
(
n
,
k
)
SG(n,k)
SG(n,k)。
时间复杂度
O
(
N
V
log
V
)
\mathcal O(N\sqrt {V\log V})
O(NVlogV)。
#include <bits/stdc++.h>
using namespace std;
int calc(int n,int k) {
while (n%k!=0) {
int t=n/k;
n-=(n-t*k+t)/(t+1)*(t+1);
}
return n/k;
}
int main() {
int n;
scanf("%d",&n);
int s=0;
for(int i=1;i<=n;i++) {
int x,y;
scanf("%d%d",&x,&y);
s^=calc(x,y);
}
puts((s)?"Takahashi":"Aoki");
return 0;
}