• [HAOI2015]数组游戏


    题目大意:
      有一排n个格子,每个格子上都有一个白子或黑子,在上面进行游戏,规则如下:
      选择一个含白子的格子x,并选择一个数k,翻转x,2x,...,kx格子上的子。
      不能操作者负。

    思路:
      将“某个格子上有一个白子 ”视作游戏的一个状态。
      对于状态x,sg(x)=mex{sg(2x),sg(2x)^sg(3x),sg(2x)^sg(3x)^...^sg(kx)}。
      由于SG函数的取值只与棋盘大小和棋子位置有关,因此我们可以记忆化。
      然后我们就有了暴力构造SG函数的程序,实测只能过40%的点,大力卡常以后勉强能50%。
      而且空间显然也开不下,只能用hash_map。
      然而这题的SG函数有一些神奇的性质,例如,对于大小为10的棋盘,当x分别为1~10时,sg(x)分别为:
      4 1 2 2 2 1 1 1 1 1
      我们将它们进行分组:
      (4)(1)(2)(2 2)(1 1 1 1 1)
      可以发现,当不同棋子可以往后跳的步数相同时,它们的SG函数相同。
      显然可以把它们分为2sqrt(n)组。
      其中前sqrt(n)组都是一个子一组,后sqrt(n)组都是很多个一组。
      这样,以sqrt(n)为界,对于我们需要的函数,判断一下参数的范围即可。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cctype>
     4 inline int getint() {
     5     char ch;
     6     while(!isdigit(ch=getchar()));
     7     int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int N=100000;
    12 int sg[N][2],mex[N];
    13 int n,block;
    14 inline int next(const int &x,const int &y) {
    15     return x==y?x+1:y/(y/(x+1));
    16 }
    17 void getsg() {
    18     for(register int i=1;i<=n;i=next(i,n)) {
    19         for(register int k=2,tmp=0;k<=i;k=next(k,i)) {
    20             int x=i/k;
    21             int t=(x>block)?sg[n/x][1]:sg[x][0];
    22             mex[tmp^t]=i;
    23             if((i/x-i/(x+1))&1) tmp^=t;
    24         }
    25         int tmp=1;
    26         while(mex[tmp]==i) tmp++;
    27         ((i>block)?sg[n/i][1]:sg[i][0])=tmp;
    28     }
    29 }
    30 int main() {
    31     n=getint();
    32     block=floor(sqrt(n));
    33     getsg();
    34     for(register int m=getint();m;m--) {
    35         int ans=0;
    36         for(register int w=getint();w;w--) {
    37             const int x=getint();
    38             ans^=(n/x>block)?sg[n/(n/x)][1]:sg[n/x][0];
    39         }
    40         puts(ans?"Yes":"No");
    41     }
    42     return 0;
    43 }

    暴力构造SG函数的程序: 

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<cstring>
     5 #include<ext/hash_map>
     6 inline int getint() {
     7     char ch;
     8     while(!isdigit(ch=getchar()));
     9     int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 __gnu_cxx::hash_map<int,int> sg,mex;
    14 int n;
    15 int getsg(const int x) {
    16     if(sg.count(x)) return sg[x];
    17     for(int k=2,tmp=0;k<=n/x;k++) {
    18         tmp^=getsg(x*k);
    19         mex[tmp]=x;
    20     }
    21     for(sg[x]=1;mex[sg[x]]==x;sg[x]++);
    22     return sg[x];
    23 }
    24 int main() {
    25     n=getint();
    26     for(int i=n;i;i--) getsg(i);
    27     for(int m=getint();m;m--) {
    28         int ans=0;
    29         for(int w=getint();w;w--) {
    30             ans^=getsg(getint());
    31         }
    32         puts(ans?"Yes":"No");
    33     }
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    WebSocket
    使用fiddler将网站上的css js重定向至本地文件
    chrome浏览器调试线上文件映射本地文件
    xul 创建一个按钮
    模板小程序】求小于等于N范围内的质数
    哈希-------开放寻址法-------暴雪哈希
    建造者模式(build pattern)-------创造型模式
    抽象工厂模式(abstract factory pattern)------创造型模式
    工厂模式(factory pattern) ------创造型模式
    文件名中含有连续字符abc,相应文件中也含有字符串abc
  • 原文地址:https://www.cnblogs.com/skylee03/p/7610878.html
Copyright © 2020-2023  润新知