多项式多点求值

抄的板子略有修改

#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;
}
View Code

 

posted @ 2021-10-12 14:33  尹吴潇  阅读(28)  评论(0编辑  收藏  举报