Codefroces 850C Arpa and a game with Mojtaba
Description
两个人Van♂游戏。给出$n$个正整数$ai$两人轮流操作,每次选出一个素数$p$和一个幂数$k$,选择的前提为该$n$个数中有$p^{k}$的倍数。接着将所有的$p^{k}$的倍数除以$p^{k}$。变成新的序列,继续操作。不能操作者为败,问先手是否必胜。
1≤100≤n,1≤ai≤109
Examples
Input
4
1 1 1 1
Output
Arpa
Input
4
1 1 17 17
Output
Mojtaba
Input
4
1 1 17 289
Output
Arpa
Input
5
1 2 3 4 5
Output
Arpa
不同质因数不互相影响
于是分开讨论每个质因数的SG值
压缩状态,如果一个数含有k个p
即$a[i]%p^{k}==0$
那么状态中第k-1位为1
那么枚举每一次的k,求出SG值
最后将每个质因数的答案取Nim和
不过状态可能会很大,用map
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 map<int,int>sg; 9 int n,a[101],pri[100001],Max[100001],cnt,ans; 10 map<int,int>vis; 11 int qpow(int x,int y) 12 { 13 int res=1; 14 while (y) 15 { 16 if (y&1) res=res*x; 17 x=x*x; 18 y>>=1; 19 } 20 return res; 21 } 22 int get_SG(int S) 23 {int i,p,SS,t; 24 if (sg.count(S)) return sg[S]; 25 if (S==0) return 0; 26 map<int,int>v; 27 t=0;SS=S; 28 while (SS) 29 { 30 SS>>=1; 31 t++; 32 } 33 for (i=0;i<t;i++) 34 { 35 p=i+1,SS=S; 36 v[get_SG((SS>>p)|(((1<<p-1)-1)&S))]=1; 37 } 38 for (p=0;;p++) 39 if (v.count(p)==0) break; 40 return sg[S]=p; 41 } 42 int main() 43 {int i,j,tot,k; 44 cin>>n; 45 for (i=1;i<=n;i++) 46 { 47 scanf("%d",&a[i]); 48 int x=a[i],k=sqrt(x); 49 for (j=2;j<=k;j++) 50 {tot=0; 51 while (x%j==0) 52 { 53 tot++; 54 if (vis[j]==0) pri[++cnt]=j,vis[j]=cnt; 55 x/=j; 56 } 57 Max[vis[j]]=max(tot,Max[vis[j]]); 58 } 59 if (x!=1) 60 { 61 if (vis[x]==0) pri[++cnt]=x,vis[x]=cnt; 62 Max[vis[x]]=max(Max[vis[x]],1); 63 } 64 } 65 ans=0; 66 for (i=1;i<=cnt;i++) 67 { 68 sg.clear(); 69 int S=0; 70 for (j=1;j<=n;j++) 71 { 72 for (k=Max[i];k>=1;k--) 73 { 74 if (a[j]%qpow(pri[i],k)==0) 75 { 76 S|=(1<<k-1); 77 break; 78 } 79 } 80 } 81 ans^=get_SG(S); 82 } 83 if (ans==0) printf("Arpa\n"); 84 else printf("Mojtaba\n"); 85 }