HDU 6061 RXD and functions

xiaoxiao2021-02-28  125

通过二项式,可以得出: bk=ni=0ciCkibiasni bk=ni=0cii!k!(ik)!biasni k!bk=ni=0(cii!)biasik(ik)! 看上去可以用FFT快速计算 k!bk 建立两个数组 Ai=cii! Bi=biasni(ni)! i>n 时, Ai=Bi=0 可以得到 k!bk=k+ni=0AiBk+ni 然后卷积一下就好了。

#include<bits/stdc++.h> using namespace std; const int MAXN=1<<18; const long long mod=998244353; const int G=3; long long rev[MAXN],w[2][MAXN]; long long fac[MAXN],inv[MAXN]; long long A[MAXN],B[MAXN]; long long pw[MAXN],ipw[MAXN]; long long c[MAXN],ans[MAXN]; int n; long long powmod(long long x,long long p) { long long ret=1; while(p) { if(p&1) ret=ret*x%mod; x=x*x%mod; p>>=1; } return ret; } void init() { fac[0]=1; for(int i=1;i<MAXN;i++) fac[i]=fac[i-1]*i%mod; inv[MAXN-1]=powmod(fac[MAXN-1],mod-2); for(int i=MAXN-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; } void initfft(int n) { int i,k,x,y,v,dv; for(i=0;i<=n-1;i++) { x=i; y=0; for(k=1;k<n;k<<=1,x>>=1) { (y<<=1)|=(x&1); } rev[i]=y; } v=powmod(G,(mod-1)/n); dv=powmod(v,mod-2); w[0][0]=w[1][0]=1; for(i=1;i<=n-1;i++) { w[0][i]=w[0][i-1]*v%mod; w[1][i]=w[1][i-1]*dv%mod; } } inline void fft(long long *A,int n,int ff) { int i,j,k,t,l,v,x,y; for(i=0;i<=n-1;i++) { if(i<rev[i]) swap(A[i],A[rev[i]]); } for(i=1;i<n;i<<=1) { for(j=0,t=n/(i<<1);j<n;j+=(i<<1)) { for(k=0,l=0;k<i;k++,l+=t) { x=A[i+j+k]*w[ff][l]%mod; y=A[j+k]; A[j+k]=(x+y)%mod; A[i+j+k]=(y+mod-x)%mod; } } } if(ff) { v=powmod(n,mod-2); for(i=0;i<=n-1;i++) A[i]=A[i]*v%mod; } } void move(long long *f,int bias,long long *g) { int i,inv_bias,m; if(bias==0) { for(i=0;i<=n;i++) g[i]=f[i]; return; } bias=(mod-bias)%mod; pw[0]=1;//pw[i]表示bias的i次方 for(i=1;i<=n;i++) pw[i]=pw[i-1]*bias%mod; ipw[0]=1;//ipw[i]表示bias的-i次方 inv_bias=powmod(bias,mod-2); for(i=1;i<=n;i++) ipw[i]=ipw[i-1]*inv_bias%mod; m=1; while(m<=2*n+2)//设置m为2的整次幂 m<<=1; for(i=0;i<=m-1;i++) A[i]=B[i]=0; initfft(m);//初始化权值 for(i=0;i<=n;i++) A[i]=f[i]*fac[i]%mod; for(i=0;i<=n;i++) B[n-i]=pw[i]*inv[i]%mod; fft(A,m,0);//正变换 fft(B,m,0); for(i=0;i<=m-1;i++)//卷积 A[i]=A[i]*B[i]%mod; fft(A,m,1);//逆变换 for(i=0;i<=n;i++) g[i]=A[i+n]*inv[i]%mod; } int main() { long long i,m,x,bias; init(); while(~scanf("%d",&n)) { for(i=0;i<=n;i++) scanf("%lld",&c[i]); bias=0; scanf("%lld",&m); for(i=1;i<=m;i++) { scanf("%lld",&x); bias=(bias+x)%mod; } move(c,bias,ans); for(i=0;i<=n;i++) printf("%lld ",ans[i]); puts(""); } }
转载请注明原文地址: https://www.6miu.com/read-48017.html

最新回复(0)