您的位置:首页 > 其它

CodeForces 317 D.Game with Powers(博弈论)

2017-08-27 12:57 447 查看
Description

两个人Vasya和Petya玩游戏,从1 ~ n中取数,Vasya先取,如果x之前已经被取过则所有x的正整数次幂都不能被取,谁先没有数字可以取谁输,问谁赢

Input

一个正整数n(1≤n≤109)

Output

输出胜者

Sample Input

1

Sample Output

Vasya

Solution

如果x不是任一y(<x)的正整数次幂,则把所有x的正整数次幂的数归为一类记为Pow(x),显然任意两类不交,且任一类的规模不超过log2n ,那么问题变成若干相同的子问题,暴力打表求出SG(1)~SG(30),注意到如果x>n√,那么Pow(x)规模是1,故只需要求出所有x≤n√的Pow(x)的规模对应的SG值异或起来,再统计一下所有x>n√且不是任意y(<x)的正整数次幂的数的个数,奇数就对答案异或1(SG(1)=1)

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 33
int sg[maxn]={0,1,2,1,4,3,2,1,5,6,2,1,8,7,5,9,8,7,3,4,7,4,2,1,10,9,3,6,11,12,14};
map<int,int>m;
int solve(int n)
{
if(n==0)return 0;
if(m.find(n)!=m.end())return m
;
int f[maxn];
memset(f,0,sizeof(f));
for(int i=1;i<=30;i++)
if(n&(1<<i))
{
int tn=n;
for(int j=i;j<=30;j+=i)
if(n&(1<<j))
tn^=(1<<j);
f[solve(tn)]=1;
}
for(int i=0;;i++)
if(!f[i])return m
=i;
}
void init()
{
m.clear();
sg[0]=0;
for(int i=1;i<=30;i++)sg[i]=solve((1<<(i+1))-2);
}
set<int>s;
int vis[55555];
int main()
{
//init();
//for(int i=0;i<=30;i++)printf("%d ",sg[i]);
int n;
while(~scanf("%d",&n))
{
s.clear();
memset(vis,0,sizeof(vis));
int ans=0;
for(ll i=2;i*i<=n;i++)
if(!vis[i])
{
int num=0;
for(ll j=i;j<=n;j*=i)
{
num++,s.insert(j);
if(j*j<=n)vis[j]=1;
}
//printf("num=%d\n",num);
ans^=sg[num];
}
if((n-s.size())&1)ans^=1;
printf("%s\n",ans?"Vasya":"Petya");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: