Codeforces Round #188 (Div. 1) D. Game with Powers

本题的关键是要发现可以把数字分成很多组,每组为{x^1,x^2,...,x^n},那么问题就是求出每组的sg函数,然后异或得解。又可以发现每组的sg值只和n有关,而且n的值小于30。那么我们就可以暴力求出1到30对应的sg函数。暴力求解时枚举去掉那个数字,求出所有子状态sg的mex值即可。我用一个数去状压有哪些数,再加个map去记忆化搜索。具体见代码:

#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#include <cstring>
#include <vector>
#define MOD 1000000007
using namespace std;
bool vis[40000];
map<int,int>mp;
__int64 POW(__int64 a,int b)
{
	__int64 res=1;
	while(b)
	{
		if(b&1)
			res=res*a;
		a=a*a;
		b>>=1;
	}
	return res;
}
int dfs(int x)
{
	if(mp.find(x)!=mp.end())
		return mp[x];
	if(x==0)
		return mp[x]=0;
	bool vis[40]={0};
	int tmp=0,mx=29;
	for(;mx>=0;mx--)
		if(x&(1<<mx))
			break;
	for(int i=1;i<=mx;i++)
	{
		if((x&(1<<i))==0)
			continue;
		tmp=0;
		for(int j=1;j<=mx;j++)
		{
			if((x&(1<<j))==0)
				continue;
			if(j%i==0)
				continue;
			tmp|=(1<<j);
		}
		vis[dfs(tmp)]=1;
	}
	for(int i=0;;i++)
	{
		if(vis[i]==0)
		{
			mp[x]=i;
			return i;
		}
	}
}
int SG[30]={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};
int main()
{
	/*  
		find SG:
			SG[0]=0;
			for(int i=1;i<30;i++)
			{
				int tmp=0;
				for(int j=1;j<=i;j++)
					tmp|=(1<<j);
				SG[i]=dfs(tmp);
				printf("%d ",SG[i]);
			}
	*/
	int n;
	scanf("%d",&n);
	int sg=0,rest=n;
	for(int i=2;i*i<=n;i++)
	{
		if(vis[i])
			continue;
		int cnt=0;
		for(int j=1;POW(i,j)<=n;j++)
		{
			int k=POW(i,j);
			cnt++;
			if((__int64)k*k<=n)
				vis[k]=1;
		}
		sg=sg^SG[cnt];
		rest-=cnt;
	}
	rest%=2;
	sg=sg^rest;
	if(sg)
		puts("Vasya");
	else
		puts("Petya");
	//system("pause");
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值