• 【洛谷P4389】—付公主的背包(多项式Exp+生成函数)


    传送门


    考虑直接构造生成函数f(x)=i=0ivmxiv=11xvf(x)=sum_{i=0}^{ivle m}x^{iv}=frac 1 {1-x^v}
    但是所有直接乘起来是O(nmlog)O(nmlog)

    考虑对所有函数取对数,加起来之后再ExpExp回来
    但是直接取LnLn也不可取

    考虑令g(x)=Ln(f(x))g(x)=Ln(f(x))
    取导后
    g(x)=f(x)f(x)=(1xv)i=0ivmivxiv1g'(x)=frac{f'(x)}{f(x)}=(1-x^v)sum_{i=0}^{ivle m}iv*x^{iv-1}

             =i=0ivmivxiv1i=0ivmivx(i+1)v1 =sum_{i=0}^{ivle m}iv*x^{iv-1}-sum_{i=0}^{ivle m}iv*x^{(i+1)*v-1}

             =i=0ivmvxiv1 =sum_{i=0}^{ivle m}vx^{iv-1}

    还原则得到
    g(x)=i=1ivmvivxivg(x)=sum_{i=1}^{ivle m}frac{v}{iv}x^{iv}

            =i=0ivm1ixiv =sum_{i=0}^{ivle m}frac{1}{i}x^{iv}

    考虑对于一个价值的vv
    只会出现mvfrac m v
    所以把v=[1,m]v=[1,m]全部计算得到gg的复杂度是O(mlogm)O(mlogm)

    然后做一次ExpExp还原回来就是了

    复杂度O(mlogm)O(mlogm)

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define re register
    #define pb push_back
    #define cs const
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    cs int mod=998244353,G=3;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?(a+=mod):0;}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){
    	for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
    }
    cs int N=100005;
    #define poly vector<int>
    int rev[N<<2],inv[N<<2];
    int n,m,v[N];
    inline void ntt(poly &f,int lim,int kd){
    	for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
    	for(int a0,a1,mid=1;mid<lim;mid<<=1){
    		int wn=ksm(G,(mod-1)/(mid<<1));
    		for(int i=0;i<lim;i+=(mid<<1)){
    			int w=1;
    			for(int j=0;j<mid;j++,Mul(w,wn)){
    				a0=f[i+j],a1=mul(w,f[i+j+mid]);
    				f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
    			}
    		}
    	}
    	if(kd==-1){
    		reverse(f.begin()+1,f.begin()+lim);
    		for(int inv=ksm(lim,mod-2),i=0;i<lim;i++)Mul(f[i],inv);
    	}
    }
    inline void init_rev(int lim){
    	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
    }
    inline poly mul(poly a,poly b){
    	int deg=a.size()+b.size()-1,lim=1;
    	while(lim<deg)lim<<=1;
    	init_rev(lim);
    	a.resize(lim),b.resize(lim);
    	ntt(a,lim,1),ntt(b,lim,1);
    	for(int i=0;i<lim;i++)Mul(a[i],b[i]);
    	ntt(a,lim,-1),a.resize(deg);
    	return a;
    }
    inline poly Inv(poly a,int deg){
    	poly b(1,ksm(a[0],mod-2)),c;
    	for(int lim=4;lim<(deg<<2);lim<<=1){
    		c=a,c.resize(lim>>1);
    		init_rev(lim);
    		c.resize(lim),b.resize(lim);
    		ntt(b,lim,1),ntt(c,lim,1);
    		for(int i=0;i<lim;i++)Mul(b[i],dec(2,mul(b[i],c[i])));
    		ntt(b,lim,-1),b.resize(lim>>1);
    	}
    	b.resize(deg);return b;
    }
    inline poly deriv(poly a){
    	for(int i=0;i<a.size();i++)a[i]=mul(a[i+1],i+1);
    	a.pop_back();return a;
    }
    inline poly integ(poly a){
    	a.pb(0);
    	for(int i=a.size()-1;i;i--)a[i]=mul(a[i-1],inv[i]);
    	a[0]=0;return a;
    }
    inline poly Ln(poly a,int lim){
    	a=integ(mul(deriv(a),Inv(a,lim))),a.resize(lim);
    	return a;
    }
    inline poly exp(poly a,int deg){
    	poly b(1,1),c;
    	for(int lim=2;lim<(deg<<1);lim<<=1){
    		c=Ln(b,lim);
    		for(int i=0;i<lim;i++)c[i]=dec(i<=m?a[i]:0,c[i]);
    		Add(c[0],1),b=mul(b,c),b.resize(lim);
    	}b.resize(deg);return b;
    }
    inline void init(){
    	inv[1]=1;
    	for(int i=2;i<N*4;i++)inv[i]=dec(0,mul(mod/i,inv[mod%i]));
    }
    poly f;
    int main(){
    	init();
    	n=read(),m=read(),f.resize(m+1);
    	for(int i=1;i<=n;i++)v[read()]++;
    	for(int i=1;i<=m;i++){
    		if(v[i]){
    			for(int j=1;j*i<=m;j++)
    			Add(f[j*i],mul(v[i],inv[j]));
    		}
    	}
    	f=exp(f,m+1);
    	for(int i=1;i<=m;i++)cout<<f[i]<<'
    ';
    }
    
  • 相关阅读:
    结巴分词 0.14 版发布,Python 中文分词库
    Lazarus 1.0.2 发布,Pascal 集成开发环境
    Android全屏 去除标题栏和状态栏
    服务器日志现 Android 4.2 传将添多项新特性
    Percona XtraBackup 2.0.3 发布
    长平狐 Android 强制设置横屏或竖屏 设置全屏
    NetBeans 7.3 Beta 发布,全新的 HTML5 支持
    CppDepend现在已经支持Linux
    GromJS 1.7.18 发布,服务器端的 JavaScript
    Apache OpenWebBeans 1.1.6 发布
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328721.html
Copyright © 2020-2023  润新知