• bzoj 4589 Hard Nim——FWT


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4589

    一开始异或和为0的话先手必败。有 n 堆,每堆可以填那些数,求最后异或和为0的方案数,就是一个快速幂的异或FWT。

    注意快速幂的过程中对那些数组直接乘就行,不用总是FWT!!!

    为什么比Zinn慢了1008ms?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5e4+5,mod=1e9+7;
    int n,m,pri[5200],cnt,len,inv;
    int f[N<<2],a[N<<2],b[N<<2];
    bool vis[N];
    int pw(int x,int k)
    {int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;}
    void fwt(int *a,bool fx)
    {
      for(int R=2;R<=len;R<<=1)
        for(int i=0,m=R>>1;i<len;i+=R)
          for(int j=0;j<m;j++)
        {
          int x=a[i+j]+a[i+m+j],y=a[i+j]+mod-a[i+m+j];
          a[i+j]=(ll)x*(fx?inv:1)%mod;
          a[i+m+j]=(ll)y*(fx?inv:1)%mod;
        }
    }
    void init()
    {
      for(int i=2;i<=50000;i++)
        {
          if(!vis[i])pri[++cnt]=i;
          for(int j=1;j<=cnt&&i*pri[j]<=50000;j++)
        {
          vis[i*pri[j]]=1;
          if(i%pri[j]==0)break;
        }
        }
      for(int i=1;i<=cnt;i++)f[pri[i]]=1;
      inv=pw(2,mod-2);
    }
    int main()
    {
      init();
      while(scanf("%d%d",&n,&m)==2)
        {
          for(len=1;len<=m;len<<=1);
          a[0]=1;for(int i=1;i<len;i++)a[i]=0;
          for(int i=0;i<=m;i++)b[i]=f[i];
          for(int i=m+1;i<len;i++)b[i]=0;
          fwt(a,0); fwt(b,0);
          while(n)
        {
          if(n&1)
            for(int i=0;i<len;i++)a[i]=(ll)a[i]*b[i]%mod;
          for(int i=0;i<len;i++)b[i]=(ll)b[i]*b[i]%mod;
          n>>=1;
        }
          fwt(a,1);
          printf("%d
    ",a[0]);
        }
      return 0;
    }
  • 相关阅读:
    如何快速把 Vue 项目升级到 webpack3
    10分钟学会ES7+ES8
    数组的32场演唱会
    你做的拷贝是真的深拷贝吗
    浅谈CSS模块化
    CORS跨域资源共享你该知道的事儿
    像VUE一样写微信小程序-深入研究wepy框架
    小型Web页打包优化(下)
    PT与PX区别
    px、pt和em的区别
  • 原文地址:https://www.cnblogs.com/Narh/p/10039990.html
Copyright © 2020-2023  润新知