题解 P4726 【【模板】多项式指数函数】
bztMinamoto · · 题解
orz这题太珂怕了……似乎都找不到几个板子参(lai)考(chao)……前置芝士又特别多……而且我写的时候牛顿迭代那里NTT数组长度写错了调了半天……然后各种地方多项式没清零又调了半天……可能是因为平时都抄板子的缘故没注意这问题……
前置芝士:多项式对数函数(这里),泰勒展开(可以看看这里第一个回答,非常……生动形象),牛顿迭代法(这里)
泰勒展开
简单来说的话,就是要求一个函数
其中
牛顿迭代
牛顿迭代可以用来求一个函数的零点,多项式牛顿迭代自然是用来求多项式的零点的,即对于一个函数
miskcoo大佬是这么说的
扯远了
然后现在就是要计算
那么变形一下得
我们设
那么代入上面牛顿迭代的公式得
然后因为
ps:这里的
然后左转把各种板子复制过来就好了
//minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#define swap(x,y) (x^=y,y^=x,x^=y)
#define mul(x,y) (1ll*x*y%P)
#define add(x,y) (x+y>=P?x+y-P:x+y)
#define dec(x,y) (x-y<0?x-y+P:x-y)
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=0;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*10+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[1<<21],z[20];int K=-1,Z;
inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
inline void print(int x){
if(K>1<<20)Ot();if(x<0)sr[++K]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++K]=z[Z],--Z);sr[++K]=' ';
}
const int N=500005,P=998244353;
inline int ksm(int a,int b){
int res=1;
while(b){
if(b&1) res=mul(res,a);
a=mul(a,a),b>>=1;
}
return res;
}
int n,r[N],A[N],B[N],C[N],D[N],F[N],G[N],O[N],f[N],g[N],inv[N];
void init(int limit){
for(int i=0,l=limit<<1;i<=l;++i) inv[i]=ksm(i,P-2);
}
void NTT(int *A,int type,int len){
int limit=1,l=0;
while(limit<len) limit<<=1,++l;
for(int i=0;i<limit;++i)
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<limit;++i)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=1;mid<limit;mid<<=1){
int R=mid<<1,Wn=ksm(3,(P-1)/R);O[0]=1;
for(int j=1;j<mid;++j) O[j]=mul(O[j-1],Wn);
for(int j=0;j<limit;j+=R){
for(int k=0;k<mid;++k){
int x=A[j+k],y=mul(O[k],A[j+k+mid]);
A[j+k]=add(x,y),A[j+k+mid]=dec(x,y);
}
}
}
if(type==-1){
reverse(A+1,A+limit);
for(int i=0,invl=inv[limit];i<limit;++i)
A[i]=mul(A[i],invl);
}
}
void Inv(int *a,int *b,int len){
if(len==1) return (void)(b[0]=inv[a[0]]);
Inv(a,b,len>>1);
for(int i=0;i<len;++i) C[i]=a[i],D[i]=b[i];
NTT(C,1,len<<1),NTT(D,1,len<<1);
for(int i=0,l=(len<<1);i<l;++i) C[i]=mul(mul(C[i],D[i]),D[i]);
NTT(C,-1,len<<1);
for(int i=0;i<len;++i) b[i]=dec(add(b[i],b[i]),C[i]);
for(int i=0,l=(len<<1);i<l;++i) C[i]=D[i]=0;
}
void Direv(int *A,int *B,int len){
for(int i=1;i<len;++i) B[i-1]=mul(A[i],i);B[len-1]=0;
}
void Inter(int *A,int *B,int len){
for(int i=1;i<len;++i) B[i]=mul(A[i-1],inv[i]);B[0]=0;
}
void Ln(int *a,int *b,int len){
Direv(a,A,len),Inv(a,B,len);
NTT(A,1,len<<1),NTT(B,1,len<<1);
for(int i=0,l=len<<1;i<l;++i) A[i]=mul(A[i],B[i]);
NTT(A,-1,len<<1),Inter(A,b,len<<1);
for(int i=0,l=len<<1;i<l;++i) A[i]=B[i]=0;
}
void Exp(int *a,int *b,int len){
if(len==1) return (void)(b[0]=1);
Exp(a,b,len>>1),Ln(b,F,len);
F[0]=dec(a[0]+1,F[0]);
for(int i=1;i<len;++i) F[i]=dec(a[i],F[i]);
NTT(F,1,len<<1),NTT(b,1,len<<1);
for(int i=0,l=len<<1;i<l;++i) b[i]=mul(b[i],F[i]);
NTT(b,-1,len<<1);
for(int i=len,l=(len<<1);i<l;++i) b[i]=F[i]=0;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
for(int i=0;i<n;++i) f[i]=read();
int len;for(len=1;len<=n;len<<=1);init(len);
Exp(f,g,len);
for(int i=0;i<n;++i) print(g[i]);
Ot();
return 0;
}