zoukankan      html  css  js  c++  java
  • BZOJ 4589 Hard Nim(FWT+博弈论+快速幂)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4589

    【题目大意】

      有n堆石子,每堆都是m以内的质数,请问后手必胜的局面有几种

    【题解】

      后手必胜,则sg为0,那么就是求n个m以内的数xor为0的情况有几种,
      首先筛出素数,保存素数的个数数组,利用FWT计算c[i^j]=a[i]*b[j],
      计算n次的结果逆向变化回来就是最终的sg个数数组,
      在计算n次c[i]=a[i]*b[i]的过程中,等价于计算c[i]=a[i]^n,
      这里我们可以用快速幂优化一个log。

    【代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int N=100000;
    const LL mod=1e9+7;
    LL a[N],u;
    int p[N],n,m;
    void FWT(LL*a,int n){
        for(int d=1;d<n;d<<=1)for(int m=d<<1,i=0;i<n;i+=m)for(int j=0;j<d;j++){
            LL x=a[i+j],y=a[i+j+d];
            a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
        }
    }
    void UFWT(LL*a,int n){
        for(int d=1;d<n;d<<=1)for(int m=d<<1,i=0;i<n;i+=m)for(int j=0;j<d;j++){
            LL x=a[i+j],y=a[i+j+d];
            a[i+j]=(x+y)%mod*u%mod,a[i+j+d]=(x-y+mod)%mod*u%mod;
        }
    }
    LL pow(LL a,LL b,LL p){LL t=1;for(a%=p;b;b>>=1LL,a=a*a%p)if(b&1LL)t=t*a%p;return t;}
    int main(){
        for(int i=2;i<=50000;i++)p[i]=1;
        for(int i=2;i<=50000;i++)if(p[i]){
            for(int j=2;i*j<=50000;j++)p[i*j]=0;
        }u=pow(2,mod-2,mod);
        while(~scanf("%d%d",&n,&m)){
            int len=1;while(len<=m)len<<=1;
            for(int i=0;i<len;i++)a[i]=p[i]&(i<=m);
            FWT(a,len);
            for(int i=0;i<len;i++)a[i]=pow(a[i],n,mod);
            UFWT(a,len);
            printf("%lld
    ",a[0]);
        }return 0;
    }
  • 相关阅读:
    【C++ Primer Chapter 3 总结】Library vector & string Type
    【C++ Primer Chapter 4 总结】左值 & 右值
    【C++ Primer Chapter 6 总结】函数
    mysql添加索引
    注册plsql
    挑战答题小程序
    开源答题小程序
    答题如何防止作弊
    党史知识答题活动小程序复盘整理
    党史学习教育答题活动复盘
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj4589.html
Copyright © 2011-2022 走看看