题目大意:
有
堆石子,每堆石子有
个,有一个数
现在两个人博弈,每
个人每次至多可以拿走数量的为
石子,
为当前这一堆石子的
数量,谁不能拿就输了,求谁赢。
思路:
这一看就是SG函数的题目,然后就不会做了。。。
我们固定了
的值为
后打表:
0 0 1 0 1 2 0 1 3 2
然后发现在
时候,SG就等于
,这个时候SG函数的值是由前面
个数决定的,根据SG函数的定义,不难发现,前面的
个数就是
到
,但是顺序肯定是打乱的。
如何求
时的函数值呢?发现当整除k相等的时候,都是由这个点往前
个数的SG函数的值决定的,由于整除的时候的值我们是知道的,往后推一个就相当于
的值到了后面(这相当于是一个循环)。
然后我们就可以递归求函数了。但是会T。
每次往前递归是将坐标减去了
,当k很大的时候会递归很多次,但是发现当k很大时候很长的一段区间减去的值都是相同的。所以我们直接一次性减去很多个相同的就可以了。
代码好短。。。
/*======================
* Author : ylsoi
* Problem : ARC91F
* Algorithm : SG
* Time : 2018.6.2
* ====================*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstring>
#include<climits>
using namespace std;
void File(){
freopen("ARC91F.in","r",stdin);
freopen("ARC91F.out","w",stdout);
}
template<typename T>bool chkmax(T &_,T __){return _<__ ? (_=__,1) : 0;}
template<typename T>bool chkmin(T &_,T __){return _>__ ? (_=__,1) : 0;}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define inf INT_MAX
const int maxn=1000+10;
int n,a,k,ans;
int get_SG(int x){
//cout<<x<<endl;
if(x%k==0)return x/k;
if((x-(x/k)-1)/k!=x/k)return get_SG(x-(x/k)-1);
int b=x-x/k*k,t=b/((x/k)+1);
return get_SG(x-t*((x/k)+1));
}
int main(){
File();
cin>>n;
REP(i,1,n){
cin>>a>>k;
ans^=get_SG(a);
}
if(ans)puts("Takahashi");
else puts("Aoki");
return 0;
}