CF850C

学习 SG 基础题。

首先发现每个质数之间是独立的,于是分成了若干个子游戏。

考虑如何计算每个子游戏的 SG 值。一开始没搞懂为什么可以状压,看了大佬代码才明白:对于一个质数 \(p\)\(p^k\) 对答案是否有影响,只和这个 \(k\) 是否出现有关。所以将 \(k\) 的出现状态情况成二进制数 \(u\),则它的所有后继状态 \(v\) 可以表示为 \((u>>k)|(((1<<(k-1))-1)\&u)\),其中 \(k\) 为该次选择 \(p^k\)。然后直接套用 SG 函数的计算方式即可。

计算出每个子游戏的 SG 值,最后套用 SG 定理即可。

注意到不同质数,状态相同,得到答案也相同。使用记忆化优化时间复杂度。具体复杂度我也不会算啊。

code:

点击查看代码
int n,m;
map<int,int> mp,f;//数据范围较大,使用 map
int calc(int u){
	if(!u)
		return 0;
	if(mp.count(u))
		return mp[u];
	set<int> st;
	for(int i=1;i<=30;i++){
		int v=(u>>i)|(((1<<(i-1))-1)&u);
		if(v==u)
			break;
		st.insert(calc(v));
	}
	for(int i=0;i<=100;i++){
		if(!st.count(i))
			return mp[u]=i;
	}//SG 函数取 mex
}
void solve(){
	scanf("%d",&n);
	for(int i=1,x;i<=n;i++){
		scanf("%d",&x);
		for(int j=2;j*j<=x;j++){
			int cnt=0;
			while(x%j==0)
				x/=j,cnt++;
			if(cnt>0)
				f[j]|=1<<(cnt-1);
		}
		if(x>1)
			f[x]|=1;
	}//质因数分解
	int ans=0;
	for(auto i=f.begin();i!=f.end();i++)
		ans^=calc(i->second);//SG 定理
	if(!ans)
		puts("Arpa");
	else
		puts("Mojtaba");
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)solve();
}
posted @ 2023-12-23 21:49  yinhee  阅读(32)  评论(0)    收藏  举报