[CodeForces850C]Arpa and a game with Mojtaba

题目大意:
  给你一个包含n个数的数列,两个人轮流对数列进行如下操作:
  选择一个质数p和一个正整数k,将数列中所有能被p^k整除的数除以p^k。
  最后不能操作者负。
  问先手是否有必胜策略。

思路:
  显然,结果不直接与数列中数的值有关,而与数列中每个数的质因数及其次数有关,因此我们可以将每个质因数分开考虑。
  枚举数列中出现的每一个质因数p,对数列中的数除去p^k就相当于将p对应的次数减去k。
  如果不同的数对于同一个质因数p,对应的次数相同,那么无论除去p的几次,对于这两个数的影响都是一样的。
  那么我们只需要将不同的质数作为我们的子游戏,游戏状态记录p出现次数(即,如果一个数中包含17,一个数中包含17^2,那么就记录1和2)。
  极限情况,2^31>1e9,那么对于每一个质数,我们可以用一个int类型状压记录出现次数。
  即,若状态s的第i位为1,则p^i在数列中出现。
  求SG函数的时候,我们可以发现SG函数的取值仅与出现次数,即状态s有关,而与具体是哪个质数无关。
  我们可以从s的最高位枚举,依次考虑把s在i后面的位数减掉的情况,这样,较高的次数在降次以后会加到较低的位数,这一操作可以用位运算(x%si)|(x/si)表示。
  对于边界情况,s=1时,表示数列中已经没有这样的质因数,SG值显然是0。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<cstring>
 6 #include<ext/hash_map>
 7 inline int getint() {
 8     register char ch;
 9     while(!isdigit(ch=getchar()));
10     register int x=ch^'0';
11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
12     return x;
13 }
14 const int N=100;
15 __gnu_cxx::hash_map<int,int> sg;
16 int a[N];
17 inline int count(int &x,const int &p) {
18     int ret=0;
19     while(!(x%p)) {
20         ret++;
21         x/=p;
22     }
23     return ret;
24 }
25 int getsg(const int x) {
26     if(sg.count(x)) {
27         return sg[x];
28     }
29     if(x==1) return sg[x]=0;
30     int si=1<<30;
31     while(!(x&si)) si>>=1;
32     int mex[10000];
33     memset(mex,0,sizeof mex);
34     while(si!=1) {
35         mex[getsg((x%si)|(x/si))]=x;
36         si>>=1;
37     }
38     int tmp=0;
39     while(mex[tmp]==x) tmp++;
40     return sg[x]=tmp;
41 }
42 int main() {
43     int n=getint();
44     for(int i=0;i<n;i++) {
45         a[i]=getint();
46     }
47     int ans=0;
48     for(int i=0;i<n;i++) {
49         int tmp=a[i];
50         for(int j=2;j<=sqrt(tmp);j++) {
51             if(!(tmp%j)) {
52                 int s=0;
53                 for(int k=0;k<n;k++) {
54                     s|=1<<count(a[k],j);
55                 }
56                 ans^=getsg(s);
57             }
58         }
59         if(a[i]!=1) {
60             int p=a[i];
61             int s=0;
62             for(int k=0;k<n;k++) {
63                 s|=1<<count(a[k],p);
64             }
65             ans^=getsg(s);
66         }
67     }
68     puts(ans?"Mojtaba":"Arpa");
69     return 0;
70 }

 

posted @ 2017-09-29 20:27  skylee03  阅读(117)  评论(0编辑  收藏  举报