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 }
  • 相关阅读:
    BIEE建模参考规范
    informatica 学习日记整理
    Web Service 的工作原理
    Oracle 时间差计算
    oracle基础知识
    Oracle 外连接和 (+)号的用法
    根据appId匹配项目名称
    vue技术分享-你可能不知道的7个秘密
    echarts3 迁徙图 迁入迁出
    ES6学习笔记
  • 原文地址:https://www.cnblogs.com/skylee03/p/7612672.html
Copyright © 2011-2022 走看看