• Loj #6703


    考虑朴素dp。

    [f_{i,j} = f_{i-1,j} + f_{i-1,j-1}*(j+a_i) ]

    稍微转换一下下标:

    [f_{i,Delta} = f_{i-1,Delta -1} + (a_i+i-Delta)f_{i-1,Delta} ]

    拆组合意义:

    一个位置上乘了 (a_i+i) 的话代表这个位置不选,并且有 $a_i+i $ 的贡献。

    然后对于剩下的 (n) 个数, 答案是 (sum g_{n,i})

    其中 (g) 的转移:

    [g_{i,j} = g_{i-1,j -1} -j * g_{i-1,j} ]

    为了方便稍微改一下,(g_i = g_i * (-1)^i) 。新的转移是:

    [g_{i,j} = -g_{i-1,j -1} +j * g_{i-1,j} ]

    新的 dp 的组合意义是 (i) 个数分成 (j) 组的方案数,每一组有一个 (-1) 的贡献。

    考虑 (g_{?,j}) 的 EGF :

    [frac {(1-e^x)^j}{j!} ]

    然后一列相当于是可以选任意个,那么就是:

    [large e^{(1-e^x)} ]

    前面可以分治 FFT,复杂度 (O(nlog^2 n))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+5;
    typedef long long ll;
    
    const int mod=998244353;
    int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
    int sub(int a,int b){a-=b;return a<0?a+mod:a;}
    int mul(int a,int b){return (ll)a*b%mod;}
    int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
    /*math*/
    
    namespace Template_poly{
    	typedef vector<int> poly;
    	int rev[N];
    	poly poly_add(poly A,poly B){
    		A.resize(max(A.size(),B.size()));
    		for(size_t i=0;i<B.size();i++)A[i]=add(A[i],B[i]);
    		return A;
    	}
    	poly poly_sub(poly A,poly B){
    		A.resize(max(A.size(),B.size()));
    		for(size_t i=0;i<B.size();i++)A[i]=sub(A[i],B[i]);
    		return A;
    	}
    	void DFT(int *t,int n,int type){
    		int l=0;while(1<<l<n)++l;
    		for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    		for(int i=0;i<n;i++)if(rev[i]>i)swap(t[rev[i]],t[i]);
    		for(int step=1;step<n;step<<=1){
    			int wn=qpow(3,(mod-1)/(step<<1));
    			for(int i=0;i<n;i+=step<<1){
    				int w=1;
    				for(int k=0;k<step;k++,w=mul(w,wn)){
    					int x=t[i+k],y=mul(t[i+k+step],w);
    					t[i+k]=add(x,y),t[i+k+step]=sub(x,y);
    				}
    			}
    		}
    		if(type==1)return;
    		for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
    		int inv=qpow(n,mod-2);
    		for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
    	}
    	poly NTT(poly A,int n,poly B,int m){
    		static poly res,PolA,PolB;
    		PolA=A,PolB=B;
    		int len=1;while(len < n+m)len<<=1;
    		res.resize(len);
    		PolA.resize(len),PolB.resize(len);
    		DFT(&PolA[0],len,1);DFT(&PolB[0],len,1);
    		for(int i=0;i<len;i++) res[i]= mul(PolA[i],PolB[i]);
    		DFT(&res[0],len,-1);
    		res.resize(n+m-1);
    		return res;
    	}
    	poly NTT(poly A,poly B){
    		return NTT(A,A.size(),B,B.size());
    	}
    	poly poly_inv(poly A,int n){
    		if(n==1)return poly(1,qpow(A[0],mod-2));
    		int len=1<<((int)ceil(log2(n))+1);
    		poly x=poly_inv(A,(n+1)>>1),y;
    		x.resize(len),y.resize(len);
    		for(int i=0;i<n;i++)y[i]=A[i];
    		DFT(&x[0],len,1),DFT(&y[0],len,1);
    		for(int i=0;i<len;i++)x[i]=mul(x[i],sub(2,mul(x[i],y[i])));
    		DFT(&x[0],len,-1);
    		x.resize(n);
    		return x;
    	}
    	poly poly_inv(poly A){
    		return poly_inv(A,A.size());
    	}
    	poly Deri(poly A){
    		int n=A.size();
    		for(int i=1;i<n;i++)A[i-1]=mul(A[i],i);
    		A.resize(n-1);
    		return A;
    	}
    
    	poly Inte(poly A){
    		int n=A.size();
    		A.resize(n+1);
    		for(int i=n;i;i--)A[i]=mul(A[i-1],qpow(i,mod-2));
    		A[0]=0;
    		return A;
    	}
    
    	poly ln(poly A){
    		int len=A.size();
    		A=Inte(NTT(Deri(A),poly_inv(A)));
    		A.resize(len);
    		return A;
    	}
    
    	poly exp(poly A,int n){
    		if(n==1)return poly(1,1);
    		poly x=exp(A,(n+1)>>1),y;
    		x.resize(n);
    		y=ln(x);
    		for(int i=0;i<n;i++)y[i]=sub(A[i],y[i]);
    		y[0]++;
    		x=NTT(x,y);
    		x.resize(n);
    		return x;
    	}
    	poly exp(poly A){
    		return exp(A,A.size());
    	}
    
    	poly sqrt(poly A,int n){
    		if(n==1)return poly(1,1);
    		poly x=sqrt(A,(n+1)>>1),y;
    		x.resize(n),y.resize(n);
    		for(int i=0;i<n;i++)y[i]=A[i];
    		x=poly_add(NTT(poly_inv(x),y),x);
    		int inv2=qpow(2,mod-2);
    		for(int i=0;i<n;i++)
    			x[i]=mul(x[i],inv2);
    		x.resize(n);
    		return x;
    	}
    	poly sqrt(poly A){
    		return sqrt(A,A.size());
    	}
    	poly rever(poly A){
    		reverse(A.begin(),A.end());
    		return A;
    	}
    	void div(poly A,poly B,poly &C,poly &D){
    		int n=A.size(),m=B.size();
    		poly ra=rever(A),rb=rever(B);
    		ra.resize(n-m+1),rb.resize(n-m+1);
    		C=NTT(ra,poly_inv(rb));
    		C.resize(n-m+1);
    		C=rever(C);
    		D=poly_sub(A,NTT(B,C));
    		D.resize(m);
    	}
    }using namespace Template_poly;
    int n,a[N];
    
    poly Divide(int l,int r){
    	int mid = (l+r)>>1;
    	if(l==r){
    		poly ret(2,1);ret[1]=a[l];
    		return ret;
    	}return NTT(Divide(l,mid),Divide(mid+1,r));
    }
    poly A,B;
    int main()
    {
    	cin >> n;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		a[i] += i;
    	}
    	A=Divide(1,n);
    	B.resize(n+2);
    	for(int i=1,_f=1;i<=n+1;i++){
    		_f=mul(_f,i);
    		B[i] = mod-qpow(_f,mod-2);
    	}
    	B=exp(B);
    	for(int i=1,f=1;i<=n;i++){
    		f=mul(f,i);
    		B[i] = mul(B[i],f);
    	
    	}
    	int ans = 0;
    	for(int i=0;i<=n;i++){
    		int rest = n-i,d=mod-1;
    		if((rest-1)%2)d=1;
    		ans = add(ans, mul(d, mul(A[i], B[n-i])));
    	}
    	cout << sub(ans,1) << endl;
    }
    
  • 相关阅读:
    String&StringBuffer&StringBuilder区别
    linux启动流程简介
    nginx视频直播/点播服务干货分享
    Http协议的认识
    php中对象是引用类型吗?
    nginx与php-fpm 504 Gateway Time-out 排查与解决案例
    php header函数常见用途
    php魔术方法
    ajax 和jsonp 不是一码事 细读详解
    php session redis 配置
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/11801162.html
Copyright © 2020-2023  润新知