zoukankan      html  css  js  c++  java
  • [BZOJ]4589 Hard Nim

      小C在学FWT是无意间翻到的一道裸题。

    Description

      Claris和NanoApe在玩石子游戏,他们有n堆石子,规则如下:
      1. Claris和NanoApe两个人轮流拿石子,Claris先拿。
      2. 每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。
      不同的初始局面,决定了最终的获胜者,有些局面下先拿的Claris会赢,其余的局面Claris会负。
      Claris很好奇,如果这n堆石子满足每堆石子的初始数量是不超过m的质数,而且他们都会按照最优策略玩游戏,那么NanoApe能获胜的局面有多少种。
      由于答案可能很大,你只需要给出答案对10^9+7取模的值。

    Input

      输入文件包含多组数据,以EOF为结尾。
      对于每组数据:共一行两个正整数n和m。

    Output

      对于每组数据,输出一个整数作为答案。

    Sample Input

      3 7
      4 13

    Sample Output

      6
      120

    HINT

      每组数据有1<=n<=10^9,2<=m<=50000。不超过80组数据。

    Solution

      首先是Nim游戏,根据Nim游戏的结论,若所有石子的数量异或起来等于0,那么后手必胜,否则先手必胜。

      所以我们要求的是n个数有多少种取值方案会使得这n个数的异或和为0。

      我们先考虑n=2的时候怎么做。

      虽然我们知道,答案等于m以内的质数个数,但是我们还是要想一想最朴素的做法。

      枚举前一个数,枚举后一个数,看看他们的异或和是否等于0。

      这样是O(m^2)的,而且我们能够得到的信息不只是异或和为0的方案数,甚至我们连异或和为x(x>0)的方案数都知道了。

      然后仔细想想这不就是在做FWT吗?

      (快速沃尔什变换FWT:http://www.cnblogs.com/ACMLCZH/p/8022502.html

      然后n>2呢?那大概就是n个这样的数组卷积在一起吧。

      由于卷积具有结合律,所以搞个卷积快速幂就可以了。

      时间复杂度O(T*logn*mlogm)。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MM 135005
    #define mod 1000000007
    using namespace std;
    int ntw,n,m,prin,len;
    int pri[MM],a[MM],b[MM];
    bool u[MM];
    
    inline int read()
    {
        int n=0,f=1; char c=getchar();
        while (c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
        while (c>='0' && c<='9') {n=n*10+c-'0'; c=getchar();}
        return n*f;
    }
    
    void FWT(int *a,int len,int g)
    {
        register int wt,st,i,x,y;
        for (wt=1;wt<len;wt<<=1)
            for (st=0;st<len;st+=wt<<1)
                for (i=0;i<wt;++i)
                {
                    x=a[st+i]; y=a[st+wt+i];
                    a[st+i]=1LL*g*(x+y)%mod;
                    a[st+wt+i]=1LL*g*(x-y+mod)%mod;
                }
    }
    
    inline void pro(int* a,int* b,int len) {for (register int i=0;i<len;++i) a[i]=1LL*a[i]*b[i]%mod;}
    void mi(int* b,int* a,int z,int len)
    {
        FWT(b,len,1); FWT(a,len,1);
        for (;z;z>>=1,pro(a,a,len)) if (z&1) pro(b,a,len);
        FWT(b,len,ntw);
    }
    
    int main()
    {
        register int i,j;
        for (i=2;i<MM;++i)
        {
            if (!u[i]) pri[++prin]=i;
            for (j=1;i*pri[j]<MM;++j)
            {
                u[i*pri[j]]=true;
                if (i%pri[j]==0) break;
            }
        }
        ntw=(mod+1)/2;
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            for (i=1;pri[i]<=m;++i) ++a[pri[i]];
            for (len=1;len<=pri[i-1];len<<=1);
            b[0]=1;    mi(b,a,n,len);
            printf("%d
    ",b[0]);
        }
    }

    Last Word

      本来《关于快速沃尔什变换(FWT)的一点学习和思考》要借着这道题说出来的,由于篇幅过长,只好另起一篇了。

  • 相关阅读:
    Sublime Text3下使用Python,REPL的安装与快捷键设置方法
    2018最新版本Sublime Text3注册码(仅供测试交流使用)
    Simple website approach using a Headless CMS: Part 3
    Simple website approach using a Headless CMS: Part 2
    Simple Website Approach Using a Headless CMS: Part 1
    Top 19 Headless CMS for Modern Publishers
    Headless CMS
    12位至今仍在世的重要工程师,让我们来认识这些程序界的大前辈
    Linux操作系统(第二版)(RHEL 8/CentOS 8)—内容简介—前言—清华大学出版社—张同光
    List of open source real-time operating systems
  • 原文地址:https://www.cnblogs.com/ACMLCZH/p/8024234.html
Copyright © 2011-2022 走看看