zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/skylee03/p/7612672.html
Copyright © 2011-2022 走看看