【博弈论】【SG函数】Codeforces Round #188 (Div. 1) D. Game with Powers

将整个游戏可以划分成若干个互不相交的子游戏。

每个子游戏的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;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/6399720.html