将整个游戏可以划分成若干个互不相交的子游戏。
每个子游戏的sg值只与其中的数的个数有关。而这个数不会超过30。
于是可以预处理出这个sg值表。
然后从1到n枚举,对<=sqrt(n)的部分,用个set判重。
对于大于sqrt(n)的部分,统计其中不包含在之前已经划分出来的子游戏内的数的个数,如果是奇数,就再异或上1。
/* #include<cstdio> #include<cstring> #include<set> #include<map> using namespace std; map<int,int>SG; int N,n; int sg(int x) { if(SG.find(x)!=SG.end()) return SG[x]; set<int>S; for(int i=1;i<=N;++i) if((x>>(i-1))&1) { int t=x; for(int j=i;j<=N;j+=i) if((x>>(j-1))&1) t^=(1<<(j-1)); S.insert(sg(t)); } for(int i=0;;++i) if(S.find(i)==S.end()) return SG[x]=i; } int main() { freopen("test.txt","w",stdout); scanf("%d",&n); for(N=1;N<=n;++N) { SG.clear(); printf("SG[%d]=%d ",N,sg((1<<N)-1)); } return 0; } */ #include<cstdio> using namespace std; typedef long long ll; bool vis[1000001]; int SG[111],n,ans; int main() { SG[1]=1; SG[2]=2; SG[3]=1; SG[4]=4; SG[5]=3; SG[6]=2; SG[7]=1; SG[8]=5; SG[9]=6; SG[10]=2; SG[11]=1; SG[12]=8; SG[13]=7; SG[14]=5; SG[15]=9; SG[16]=8; SG[17]=7; SG[18]=3; SG[19]=4; SG[20]=7; SG[21]=4; SG[22]=2; SG[23]=1; SG[24]=10; SG[25]=9; SG[26]=3; SG[27]=6; SG[28]=11; SG[29]=12; SG[30]=14; scanf("%d",&n); ans^=1; int all=0; for(ll i=2ll;i*i<=(ll)n;++i) { if(!vis[i]) { int cnt=0; for(ll j=(ll)i;j<=(ll)n;j*=(ll)i) { if(j*j<=(ll)n) vis[j]=1; ++cnt; ++all; } ans^=SG[cnt]; } } ans^=((n-all-1)&1); puts(ans ? "Vasya" : "Petya"); return 0; }