多项式多点求值
抄的板子略有修改
#include <bits/stdc++.h> using namespace std; #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) #define ll long long #define me(x) memset(x,0,sizeof(x)) #define IL inline #define rint register int inline ll rd(){ ll x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x; } char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>void maxa(T &x,T y) { if (y>x) x=y; } template<class T>void mina(T &x,T y) { if (y<x) x=y; } template<class T>void read(T &x) { int f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while(c=gc(),c>47&&c<58) x=x*10+(c^48); x*=f; } const int mo=998244353; ll fsp(int x,int y) { if (y==1) return x; ll ans=fsp(x,y/2); ans=ans*ans%mo; if (y%2==1) ans=ans*x%mo; return ans; } struct cp { ll x,y; cp operator +(cp B) { return (cp){x+B.x,y+B.y}; } cp operator -(cp B) { return (cp){x-B.x,y-B.y}; } ll operator *(cp B) { return x*B.y-y*B.x; } int half() { return y < 0 || (y == 0 && x < 0); } }; struct re{ int a,b,c; }; const int N=5e5; const int G=3; #define I inline int #define V inline void // 空间是4倍 V check(int&x){x-=mo,x+=x>>31&mo;} namespace poly{ int lmt,w[N],r[N]; V init(int n){ int l=-1,wn; for(lmt=1;lmt<=n;)lmt<<=1,l++; rep(i,0,lmt-1)r[i]=(r[i>>1]>>1)|((i&1)<<l); wn=fsp(3,mo>>++l),w[lmt>>1]=1; rep(i,(lmt>>1)+1,lmt-1)w[i]=1ll*w[i-1]*wn%mo; dep(i,(lmt>>1)-1,1)w[i]=w[i<<1]; } V cl(int*a,int n){memset(a,0,n<<2);} I getLen(int n){return 1<<32-__builtin_clz(n);} V mul(int*a,int x,int n,int*b){while(n--)*b++=1ll**a++*x%mo;} V dot(int*a,int*b,int n,int*c){while(n--)*c++=1ll**a++**b++%mo;} V DFT(int*a,int l){ static unsigned ll tmp[N]; int u=__builtin_ctz(lmt/l),t; rep(i,0,l-1)tmp[i]=a[r[i]>>u]; for(int i=1;i^l;i<<=1)for(int j=0,d=i<<1;j^l;j+=d)rep(k,0,i-1) t=tmp[i|j|k]*w[i|k]%mo,tmp[i|j|k]=tmp[j|k]+mo-t,tmp[j|k]+=t; rep(i,0,l-1)a[i]=tmp[i]%mo; } V IDFT(int*a,int l){reverse(a+1,a+l),DFT(a,l),mul(a,mo-mo/l,l,a);} V Inv(const int*a,int n,int*b){ static int A[N],B[N],tmp[N],d,l; tmp[0]=fsp(a[0],mo-2),cl(A,d),cl(B,d); for(d=1,l=2;d<n;d<<=1,l<<=1){ copy(a,a+min(l,n),A),copy(tmp,tmp+d,B); DFT(A,l),DFT(B,l),dot(A,B,l,A),IDFT(A,l); cl(A,d),DFT(A,l),dot(A,B,l,A),IDFT(A,l); copy(A+d,A+l,tmp+d),mul(tmp+d,mo-1,d,tmp+d); } copy(tmp,tmp+n,b); } int*f[N],*g[N],bin[N<<5],*np(bin); V Mul(int*a,int*b,int n,int m,int*c){ static int A[N],B[N],l; l=getLen(n+m-1),copy(a,a+n,A),copy(b,b+m,B); DFT(A,l),DFT(B,l),dot(A,B,l,A),IDFT(A,l); copy(A,A+n+m-1,c),cl(A,l),cl(B,l); } V eva_init(int p,int l,int r,int*a){ g[p]=np,np+=r-l+2,f[p]=np,np+=r-l+2; if(l==r)return g[p][0]=1,check(g[p][1]=mo-a[l]); int lc=p<<1,rc=lc|1,mid=l+r>>1,len1=mid-l+2,len2=r-mid+1; eva_init(lc,l,mid,a),eva_init(rc,mid+1,r,a); Mul(g[lc],g[rc],len1,len2,g[p]); } V Mult(int*a,int*b,int n,int m,int*c){ static int A[N],B[N],l; l=getLen(n),copy(a,a+n,A),reverse_copy(b,b+m,B); DFT(A,l),DFT(B,l),dot(A,B,l,A),IDFT(A,l); copy(A+m-1,A+n,c); cl(A,l),cl(B,l); } V eva_work(int p,int l,int r,int*a){ if(l==r)return void(a[l]=f[p][0]); int lc=p<<1,rc=lc|1,mid=l+r>>1,len1=mid-l+2,len2=r-mid+1; Mult(f[p],g[rc],r-l+1,len2,f[lc]); eva_work(lc,l,mid,a); Mult(f[p],g[lc],r-l+1,len1,f[rc]); eva_work(rc,mid+1,r,a); } V eva(int*a,int*b,int n,int m,int*c){ static int X[N],Y[N],l; eva_init(1,1,m,b),Inv(g[1],m+1,X); reverse(X,X+m+1),Mul(a,X,n,m+1,Y); copy(Y+n,Y+n+m,f[1]),eva_work(1,1,m,c); rep(i,1,m)check(c[i]=1ll*c[i]*b[i]%mo+a[0]); } } int n,m,a[N],b[N],c[N]; int main(){ ios::sync_with_stdio(false); cin>>n>>m; n++; poly::init(max(n,m+1)<<1); rep(i,0,n-1) cin>>a[i]; rep(i,1,m) cin>>b[i]; n=max(n,m+1),poly::eva(a,b,n,max(n-1,m),c); rep(i,1,m)cout<<c[i]<<'\n'; return 0; }