• 付公主的背包 题解


    付公主的背包 题解

    Problem:

    ​ 有\(n\)种物品,每种物品体积为\(v_i\),数量无限,给定\(m\),求$ \forall s \in [1,m]\(,恰好装\)s$体积的方案数,\(1 \leq n,m \leq 10^5\)

    Solution

    ​ 考虑每一种物品的生成函数\(G_i(x)=\sum\limits_{i=0}^{\infty}x^{iv_i}=\frac{1}{1-x^{v_i}}\)

    ​ 那么总方案的生成函数就为\(F(x)=\prod\limits_{i=1}^n\frac{1}{1-x^{v_i}}\)

    ​ 感觉\(\prod\)并不好怎么转化,直接处理肯定过不了,考虑把\(\prod\)化为\(\sum\)

    ​ 两边取\(ln\),得\(lnF(x)=-\sum\limits_{i=1}^nln(1-x^{v_i})\)

    ​ 发现现在我们好像仍然没有什么好办法......那么开始推式子都试一遍

    ​ 考虑等式右边形如\(ln(1-x^k)\)的这个函数,令其为\(H(x)\)

    ​ 我们有\(H(x)'=-kx^{k-1}\frac{1}{1-x^{k}}\)

    ​ 幂级数展开:\(H(x)'=-kx^{k-1}\sum\limits_{i=0}^{\infty}x^{ki}=\sum\limits_{i=0}^{\infty}-kx^{ki+k-1}=\sum\limits_{i=1}^{\infty}-kx^{ki-1}\)

    ​ 逐项积分:\(H(x)=\sum\limits_{i=1}^{\infty}-\frac{x^{ki}}{i}\)

    ​ ??好像这个式子有点用挺好看的

    ​ 那么\(lnF(x)=\sum\limits_{i=1}^n\sum\limits_{j=1}^{m/v_i}\frac{x^{v_ij}}{j}=\sum\limits_{v=1}^{Max}\sum\limits_{i=1}^{m/v}cnt_v\frac{x^{vi}}{i}\)

    ​ 算这个式子的复杂度是可以接受的

    ​ 那么最后再多项式exp回去即可,总复杂度\(O(mlogm)\)

    Code

    #include<bits/stdc++.h>
    #define PR 3
    #define mod 998244353
    #define LL long long
    using namespace std;
    int n,m,rev[400005];
    LL F[400005],G[400005],H[400005],P[400005],R[400005],inv[400005],bar[400005];
    
    inline char Getchar(){
        static char s[1<<16],*S,*T;
        return (S==T)&&(T=(S=s)+fread(s,1,1<<16,stdin),S==T)?EOF:*S++;
    }
    
    inline int read(){
        int x=0,f=1;char ch=Getchar();
        while(ch<'0'||ch>'9'){
           if(ch=='-')f=-1;
           ch=Getchar();
        }
        while(ch>='0'&&ch<='9'){
           x=(x<<1)+(x<<3)+ch-'0';
           ch=Getchar();
        }
        return x*f;
    }
    
    inline LL quick_power(LL x,int k){
        LL res=1;
        while(k){
            if(k&1)
                res=res*x%mod;
            x=x*x%mod;k>>=1;
        }
        return res;
    }
    
    namespace Polynomial{
        
        void Derivative(LL *F,int Lim){
            for(register int i=0;i<Lim-1;++i)
                F[i]=F[i+1]*(i+1)%mod;
            F[Lim-1]=0;return;
        }
    
        void Integral(LL *F,int Lim){
            for(register int i=Lim;i;--i)
                F[i]=F[i-1]*inv[i]%mod;
            F[0]=0;return;
        }
    
        void NTT(LL *F,int Lim,int op){
            for(register int i=0;i<Lim;++i){
                if(i<rev[i])
                    swap(F[i],F[rev[i]]);
            }
            for(register int mid=1;mid<Lim;mid<<=1){
                int R=mid<<1;
                LL rt=quick_power(PR,(mod-1)/R);
                for(register int j=0;j<Lim;j+=R){
                    LL w=1;
                    for(register int k=0;k<mid;++k){
                        LL x=F[j|k],y=w*F[j|k|mid]%mod;
                        F[j|k]=(x+y)%mod;
                        F[j|k|mid]=(x-y+mod)%mod;
                        w=w*rt%mod;
                    }
                }
            }
            if(op==-1){
                reverse(F+1,F+Lim);
                LL Inv=quick_power(Lim,mod-2);
                for(register int i=0;i<Lim;++i)
                    F[i]=F[i]*Inv%mod;
            }
            return;
        }
    
        void Polyinv(int N,LL *F,LL *G){
            if(N==1){
                G[0]=quick_power(F[0],mod-2);
                return;
            }
            Polyinv(N+1>>1,F,G);
            int Lim=1,Len=-1;
            while(Lim<(N<<1))   
                Lim<<=1,++Len;
            for(register int i=0;i<Lim;++i)
                rev[i]=(rev[i>>1]>>1)|((i&1)<<Len);
            for(register int i=0;i<Lim;++i)
                H[i]=i<N?F[i]:0;
            NTT(H,Lim,+1);NTT(G,Lim,+1);
            for(register int i=0;i<Lim;++i)
                G[i]=G[i]*(2-G[i]*H[i]%mod+mod)%mod;
            NTT(G,Lim,-1);
            for(register int i=N;i<Lim;++i)
                G[i]=0;
            return;
        }
    
        void Polyln(int N,LL *F,LL *G){
            Polyinv(N,F,G);
            Derivative(F,N);
            int Lim=1,Len=-1;
            while(Lim<(N<<1))
                Lim<<=1,++Len;
            for(register int i=0;i<Lim;++i)
                rev[i]=(rev[i>>1]>>1)|((i&1)<<Len);
            NTT(F,Lim,+1);NTT(G,Lim,+1);
            for(register int i=0;i<Lim;++i)
                G[i]=F[i]*G[i]%mod;
            NTT(G,Lim,-1);
            Integral(G,N);
            return;
        }
    
        void Polyexp(int N,LL *F,LL *G){
            if(N==1){
                G[0]=1;
                return;
            }
            Polyexp(N+1>>1,F,G);
            for(register int i=0;i<(N+1>>1);++i)
                R[i]=G[i],P[i]=0;
            Polyln(N,R,P);
            P[0]=F[0]-P[0]+1;
            for(register int i=1;i<(N<<1);++i)
                P[i]=i<N?(F[i]-P[i]+mod)%mod:0;
            int Lim=1,Len=-1;
            while(Lim<(N<<1))
                Lim<<=1,++Len;
            for(register int i=0;i<Lim;++i)
                rev[i]=(rev[i>>1]>>1)|((i&1)<<Len);
            NTT(G,Lim,+1);NTT(P,Lim,+1);
            for(register int i=0;i<Lim;++i)
                G[i]=G[i]*P[i]%mod;
            NTT(G,Lim,-1);
            for(register int i=N;i<Lim;++i)
                G[i]=P[i]=R[i]=0;
            return;
        }
    
    }using namespace Polynomial;
    
    int main(){
        
        n=read();m=read()+1;
    
        inv[1]=1;
        for(register int i=2;i<=m;++i)
            inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    
        for(register int i=1;i<=n;++i)
            ++bar[read()];
    
        for(register int i=1;i<=m;++i){
            if(!bar[i])
                continue;
            for(register int j=1;i*j<=m;++j)
                F[i*j]=(F[i*j]+bar[i]*inv[j]%mod)%mod;
        }
    
        Polyexp(m,F,G);
        
        for(register int i=1;i<m;++i)
            printf("%lld\n",G[i]);
    
        return 0;
    }
    
  • 相关阅读:
    PHP chr函数 对应的AscII码
    微信小程序:样式,事件
    PHP 实现移动端极光推送(转)
    微信小程序服务器请求和上传数据,上传图片并展示,提交表单完整实例代码附效果图(转)
    大头照上传预览,并操作数据库和删除文件夹中存储的之前的图片;$_SERVER['DOCUMENT_ROOT']上传图片和删除图片的时候不要用绝对路径,可以用这个路径
    thinkphp 条件搜索分页(tp自带Page类)
    asp搭配环境
    html5手机端手指滑动选项卡滚动切换效果(转)
    tp框架实现ajax注册验证
    tp框架链接数据库的基本操作
  • 原文地址:https://www.cnblogs.com/zjy123456/p/13714814.html
Copyright © 2020-2023  润新知