zoukankan      html  css  js  c++  java
  • [SDOI2015]序列统计

    FFT优化背包

    可以推出dp式子

    乘法不可做。M是质数,变成原根

    dp式子现在是加法

    其实每次是原来的f数组,对可以转移的s集合进行卷积(即FFT优化背包)

    直接快速幂搞定

    详细一些:

    循环卷积无非就是多了一个取值的位置,每次FFT之后,一个位置再变成两个位置的和,剩下>=m的位置再变成0

    也有结合律

    注意,S中有0,而0没有原根,并且x>=1所以选择0一定不是答案。直接pass掉

    代码:

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    #define int long long
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=8005*8;
    const int mod=1004535809;
    int n,m,o;
    int len;
    int G;
    int s[N],sz;
    ll ret[N];
    ll qm(ll x,ll y,int mo){
        ll ret=1;
        while(y){
            if(y&1) ret=ret*x%mo;
            x=x*x%mo;
            y>>=1;
        }
        return ret;
    }
    ll f[N],h[N];
    int id[N];
    int rev[N];
    void fft(ll *f,int n,int c){
        for(reg i=0;i<n;++i){
            if(i<rev[i]) swap(f[i],f[rev[i]]);
        }
        for(reg p=2;p<=n;p<<=1){
            int gen;
            if(c==1) gen=qm(3,(mod-1)/p,mod);
            else gen=qm(qm(3,mod-2,mod),(mod-1)/p,mod);
            int len=p/2;
            for(reg l=0;l<n;l+=p){
                ll buf=1;
                for(reg k=l;k<l+len;++k){
                    ll tmp=buf*f[k+len]%mod;
                    f[k+len]=(f[k]-tmp+mod)%mod;
                    f[k]=(f[k]+tmp)%mod;
                    buf=buf*gen%mod;
                }
            }
        }
    }
    void calc(ll *f,ll *g,int n){
    //    cout<<"clac nn "<<n<<endl;
    //    cout<<" fff "<<endl;
    //    for(reg i=0;i<n;++i){
    //        cout<<f[i]<<" ";
    //    }cout<<endl;
    //    cout<<" ggg "<<endl;
    //    for(reg i=0;i<n;++i){
    //        cout<<g[i]<<" ";
    //    }cout<<endl;
        
        for(reg i=0;i<n;++i) h[i]=g[i];
        fft(f,n,1);fft(h,n,1);
        for(reg i=0;i<n;++i) f[i]=f[i]*h[i]%mod;
        fft(f,n,-1);
        ll inv=qm(n,mod-2,mod);
        for(reg i=0;i<n;++i) f[i]=f[i]*inv%mod,h[i]=f[i];
        for(reg i=1;i<m;++i) {
        //    cout<<f[i]<<" ";
            f[i]=(f[i]+h[i+m-1])%mod;
        }
    //    cout<<endl;
        for(reg i=m;i<n;++i) f[i]=0;
    }
    void findG(){
        for(G=2;;++G){
            bool fl=true;
            for(reg i=1;i<=m-2;++i){
                if(qm(G,i,m)==1) {
                    fl=false;break;
                }
            }
            if(fl) break;
        }    
    }
    void qsm(int y){
        memset(ret,0,sizeof ret);
        ret[0]=1;
        while(y){
            if(y&1) {
                if(ret[0]==1) memcpy(ret,f,sizeof f);
                else calc(ret,f,len);
            }
            calc(f,f,len);
    //        /cout<<" ff "<<y<<endl;
    //        for(reg i=0;i<n;++i){
    //            cout<<f[i]<<" ";
    //        }cout<<endl;
            y>>=1;
        }
    }
    int main(){
        rd(n);rd(m);rd(o);rd(sz);
        int cnt=0;
        int lp;
        for(reg i=1;i<=sz;++i){
            rd(lp);if(lp) s[++cnt]=lp;
        }
        findG();
    //    cout<<" GG "<<G<<endl;
        for(reg i=1;i<=m-1;++i){
            id[qm(G,i,m)]=i;
        }
        for(reg i=1;i<=cnt;++i) {
            s[i]=id[s[i]];
            f[s[i]]=1;
        }
        for(lp=m+m,len=1;len<lp;len<<=1);
        for(reg i=0;i<len;++i){
            rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
        }
    //    cout<<" len "<<len<<endl;
        qsm(n);
        o=id[o];
    //    cout<<" o "<<o<<endl;
        printf("%lld",ret[o]);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/1/16 21:29:34
    */
  • 相关阅读:
    拟阵学习笔记
    HNOI 2016 解题报告
    HNOI 2015 解题报告
    一类动态规划问题状态的简化
    组合数学学习笔记
    简单多项式学习笔记
    基础线代学习笔记
    后缀数据结构学习笔记
    图论学习笔记
    AT3673 [ARC085D] NRE 题解
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10283605.html
Copyright © 2011-2022 走看看