HDU6061 RXD and functions

xiaoxiao2021-02-28  110

题目链接

题意

​ 已知 f(x)=ni=0cixi ,给定一个长度为 m 的数列 A ,求 f(xmi=1ai) 的所有系数模998244353的结果。

分析

​ 赛时纠结其它题去了,没有认真推=-=。(虽然推出来了,当时也没有NTT的板子的说)

​ 以下均用 a 代替 mi=1ai

​ 将所有的 (xa)i 均拆开,并将对应 xi 的系数划分到一块,得到

f(xa)=i=0nxi(j=incjCijaji)

​ 再将组合数部分拆开得到

i=0nxi(j=incjj!(ji)!i!aji)

​ 为了便于计算,将 j j i 进行替换,得到

i=0nxi(j=0nicj+i(j+i)!j!i!aj)

​ 将内层求和中无关的变量i的部分提出,并进行简单的划分得到

i=0nxii!(j=0ni(cj+i(j+i)!)(ajj!))

​ 向卷积式凑一下,令 k=nij ,再进行一次替换得到

i=0nxii!(j+k=ni(cnk(nk)!)(ajj!))

​ 将 cnk(nk)! 在n长度进行一个翻转就能将式子转换成卷积式,再就是套一下NTT即可,具体可以看代码。

代码

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define Mp(x,y) make_pair(x,y) #define LL long long #define MAXN 100100 const int inf = 0x3fffffff; const int mmax = 1<<18; const int mod = 998244353; const int g = 3; //原根 LL quick_mod(LL a,LL b){ LL ans=1; for(;b;b/=2){ if(b&1) ans=ans*a%mod; a=a*a%mod; } return ans; } int rev(int x,int r) //蝴蝶操作 { int ans=0; for(int i=0; i<r; i++){ if(x&(1<<i)){ ans+=1<<(r-i-1); } } return ans; } void NTT(int n,LL A[],int on) // 长度为N (2的次数) { int r=0; for(;; r++){ if((1<<r)==n) break; } for(int i=0; i<n; i++){ int tmp=rev(i,r); if(i<tmp) swap(A[i],A[tmp]); } for(int s=1; s<=r; s++){ int m=1<<s; LL wn=quick_mod(g,(mod-1)/m); for(int k=0; k<n; k+=m){ LL w=1; for(int j=0; j<m/2; j++){ LL t,u; t=w*(A[k+j+m/2]%mod)%mod; u=A[k+j]%mod; A[k+j]=(u+t)%mod; A[k+j+m/2]=((u-t)%mod+mod)%mod; w=w*wn%mod; } } } if(on==-1){ for(int i=1;i<n/2;i++) swap(A[i],A[n-i]); LL inv=quick_mod(n,mod-2); for(int i=0;i<n;i++) A[i]=A[i]%mod*inv%mod; } } LL A[mmax+10],B[mmax+10]; LL ans[mmax+10]; int c[MAXN]; LL fac[MAXN]; LL ni[MAXN]; void init(){ fac[0]=ni[0]=1; for(int i=1;i<MAXN;++i) fac[i]=(fac[i-1]*i)%mod; ni[MAXN-1]=quick_mod(fac[MAXN-1],mod-2); for(int i=MAXN-2;i;i--) ni[i]=(ni[i+1]*(i+1))%mod; } int main(){ int n,m,tmp; init(); while(~scanf("%d",&n)){ LL a=0; for(int i=0;i<=n;++i) scanf("%d",&c[i]); scanf("%d",&m); for(int i=0;i<m;++i){ scanf("%d",&tmp); a-=tmp; if(a<0) a+=mod; } if(a==0){ for(int i=0;i<=n;++i) printf("%d ",c[i]); cout<<endl; continue; } B[0]=1; LL aa=1; int l=1; while(l<=2*n) l<<=1; for(int i=0;i<l;++i){ if(i<=n){ A[i]=(fac[n-i]*c[n-i])%mod; B[i]=(aa*ni[i])%mod; } else A[i]=B[i]=0; aa=(aa*a)%mod; } NTT(l,A,1); NTT(l,B,1); for(int i=0; i<l; i++) A[i]=A[i]*B[i]%mod; NTT(l,A,-1); for(int i=0;i<=n;++i) printf("%I64d ",(A[n-i]*ni[i])%mod); cout<<endl; } }
转载请注明原文地址: https://www.6miu.com/read-51234.html

最新回复(0)