• [bzoj4589]Hard Nim【FWT】


    【题目链接】
      http://www.lydsy.com/JudgeOnline/problem.php?id=4589
    【题解】
      就是求n堆石子异或和为0的方案数。
      这个东西显然满足结合律,因此倍增计算就行了。暴力的复杂度O(m2log2n)
      考虑用FWT优化转移,这是经典的xor卷积。
      复杂度O(mlog2mlog2n)

    /* --------------
        user Vanisher
        problem bzoj-4589 
    ----------------*/
    # include <bits/stdc++.h>
    # define    ll      long long
    # define    inf     0x3f3f3f3f
    # define    M       100010
    # define    N       100010
    # define    P       1000000007
    using namespace std;
    ll read(){
        ll tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    ll mypow(ll x, ll y){
        ll i=x; x=1;
        while (y>0){
            if (y%2==1) x=x*i%P;
            i=i*i%P;
            y/=2;
        }
        return x;
    }
    ll rev=mypow(2,P-2),j[N],f[M+10],p[M+10],pnum,n,m,a[N],l;
    void FWT(ll *a, ll l){
        for(ll d=1; d<l; d<<=1)  
            for(ll m=(d<<1),i=0; i<l; i+=m)  
                for(ll j=0;j<d;j++)  
                {  
                    ll x=a[i+j],y=a[i+j+d];  
                    a[i+j]=(x+y)%P,a[i+j+d]=(x-y+P)%P;  
                }
    }
    void UFWT(ll *a, ll l){
        for(ll d=1; d<l; d<<=1)  
            for(ll m=(d<<1),i=0; i<l; i+=m)  
                for(ll j=0;j<d;j++)  
                {  
                    ll x=a[i+j],y=a[i+j+d];  
                    a[i+j]=(x+y)*rev%P,a[i+j+d]=((x-y)*rev%P+P)%P;  
                }
    }
    void mypow(ll *x, ll y, ll l){
        for (ll i=0; i<l; i++) j[i]=x[i];
        for (ll i=0; i<l; i++) x[i]=1;
        while (y>0){
            if (y%2==1) for (ll i=0; i<l; i++) x[i]=(x[i]*j[i])%P;
            for (ll i=0; i<l; i++) j[i]=(j[i]*j[i])%P;
            y/=2;
        }
    }
    void getp(){
        f[1]=true;
        for (ll i=2; i<=M; i++)
            if (f[i]==false){
                p[++pnum]=i;
                for (ll j=i+i; j<=M; j+=i)
                    f[j]=true;
            }
    }
    int main(){
        getp();
        while (scanf("%lld%lld",&n,&m)!=EOF){
            memset(a,0,sizeof(a));
            for (ll i=1; p[i]<=m; i++) a[p[i]]=1;
            l=1; while (l<=m) l<<=1;
            FWT(a,l);
            mypow(a,n,l);
            UFWT(a,l);
            printf("%lld
    ",a[0]);
        }
        return 0;
    }
    
  • 相关阅读:
    第九周学习总结&实验报告(7)
    团队展示
    结对编程
    微信公众号
    编程作业
    《构建之法》
    自我介绍
    java学期总结
    14周作业
    13周总结
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135985.html
Copyright © 2020-2023  润新知