zoukankan      html  css  js  c++  java
  • BZOJ 4589: Hard Nim DP+快速幂+FWT

    朴素的DP:$f[i][j]$ 表示选了 $i$ 个数,异或值为 $j$ 的方案数.

    转移:$f[i][j]=sum_{i=1}^{m}f[i-1][k] imes isprime[p]$($p$ 异或 $k$ 等于 $j$)

    如果 $n$ 比较小的话可以直接进行 FWT 优化 DP.

    然而,这道题中 $n=10^9$,那就用快速幂优化 DP 就好啦 ~

     code:

    #include <cstdio> 
    #include <algorithm>       
    #define ll long long  
    #define N 100002 
    #define MAXM 50000
    #define mod 1000000007 
    #define setIO(s) freopen(s".in","r",stdin) // ,freopen(s".out","w",stdout)  
    using namespace std;                   
    int lim,inv,tot; 
    int ar[N],br[N],prime[MAXM],vis[MAXM];     
    int qpow(int x,int y) 
    {
        int tmp=1; 
        for(;y;y>>=1,x=(ll)x*x%mod) 
            if(y&1) tmp=(ll)tmp*x%mod;  
        return tmp; 
    }
    void FWT(int *f,int opt) 
    {            
        int i,j,k;    
        for(i=1;i<lim;i<<=1) 
        {
            for(j=0;j<lim;j+=i<<1)  
                for(k=0;k<i;++k)      
                {
                    int x=f[j+k],y=f[j+k+i];         
                    f[j+k]=(ll)(x+y)%mod;   
                    f[j+k+i]=(ll)(x-y+mod)%mod;   
                    if(opt==-1) 
                    {
                        f[j+k]=1ll*inv*f[j+k]%mod;   
                        f[j+k+i]=1ll*inv*f[j+k+i]%mod;   
                    }
                }
        }
    } 
    void init()
    {                          
        int i,j; 
        for(i=2;i<MAXM;++i) 
        { 
            if(!vis[i]) prime[++tot]=i; 
            for(j=1;j<=tot&&prime[j]*i<MAXM;++j) 
            { 
                vis[i*prime[j]]=1;  
                if(i%prime[j]==0) break;           
            }
        }     
    }
    void DP(int y) 
    {
        for(int i=0;i<lim;++i) br[i]=ar[i];                           
        while(y) 
        {
            if(y&1)
            { 
                for(int i=0;i<lim;++i) ar[i]=(ll)ar[i]*br[i]%mod; 
            }
            y>>=1; 
            for(int i=0;i<lim;++i) 
            {
                br[i]=(ll)br[i]*br[i]%mod;   
            }
        }
    }
    int main() 
    { 
        // setIO("input");            
        int i,j,n,m;                 
        inv=qpow(2,mod-2),init();       
        while(scanf("%d%d",&n,&m)!=EOF) 
        {    
            for(i=1;i<=tot&&prime[i]<=m;++i) ar[prime[i]]=1;                                         
            for(lim=1;lim<=m;lim<<=1);                     
            FWT(ar,1);         
            DP(n-1);   
            FWT(ar,-1);       
            printf("%d
    ",ar[0]);   
            for(i=0;i<lim;++i) ar[i]=br[i]=0; 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    Python-Django学习
    Python+Selenium+Pycharm
    selenium基础实例学习
    Django实例
    Django路由机制
    Selenium爬取电影网页写成csv文件
    Numpy初步
    Python matplotlib图片转化成矢量图并裁剪
    先选先赢问题
    Python退火算法在高次方程的应用
  • 原文地址:https://www.cnblogs.com/guangheli/p/12169506.html
Copyright © 2011-2022 走看看