P6800-[模板]Chirp Z-Transform【NTT】
阿新 • • 發佈:2021-07-20
正題
題目連結:https://www.luogu.com.cn/problem/P6800
題目大意
給出一個\(n\)此多項式\(P\),對於\(k\in[0,m-1]\)所有的求\(P(c^k)\)
輸出答案對\(998244353\)取模
\(1\leq n,m\leq 10^6\)
解題思路
\[g(n)=\sum_{i=0}^{n-1}a_ic^{i\times n} \]然後根據\(i\times n=\binom{i+n}{2}-\binom{i}{2}-\binom{n}{2}\)有
\[g(n)=c^{-\binom{n}{2}}\sum_{i=0}^{n-1}a_ic^{\binom{i+n}{2}}c^{-\binom{i}{2}} \]然後這是一個反著卷積的形式,直接上NTT就好了
時間複雜度\(O(n\log n)\)
code
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=4e6+10,P=998244353; ll n,m,c,a[N],r[N],F[N],G[N]; ll power(ll x,ll b){ ll ans=1;b%=P-1; while(b){ if(b&1)ans=ans*x%P; x=x*x%P;b>>=1; } return ans; } ll C(ll n) {return n*(n-1)/2;} void NTT(ll *f,ll n,ll op){ for(ll i=0;i<n;i++) if(i<r[i])swap(f[i],f[r[i]]); for(ll p=2;p<=n;p<<=1){ ll tmp=power(3,(P+1)/p),len=p>>1; if(op==-1)tmp=power(tmp,P-2); for(ll k=0;k<n;k+=p){ ll buf=1; for(ll i=k;i<k+len;i++){ ll tt=f[i+len]*buf%P; f[i+len]=(f[i]-tt+P)%P; f[i]=(f[i]+tt)%P; buf=buf*tmp%P; } } } if(op==-1){ ll invn=power(n,P-2); for(ll i=0;i<n;i++) f[i]=f[i]*invn%P; } return; } signed main() { scanf("%lld%lld%lld",&n,&c,&m); ll inv=power(c,P-2); for(ll i=0;i<n;i++) scanf("%lld",&a[i]); for(ll i=0;i<n+m;i++) F[i]=power(c,C(n+m-i-1)); for(ll i=0;i<n;i++) G[i]=a[i]*power(inv,C(i))%P; ll len=1; while(len<n+m)len<<=1; for(ll i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)?(len>>1):0); NTT(F,len,1);NTT(G,len,1); for(ll i=0;i<len;i++)F[i]=F[i]*G[i]%P; NTT(F,len,-1); for(ll i=n+m-1;i>=n;i--) printf("%lld ",F[i]*power(inv,C(n+m-i-1))%P); return 0; }