【NTT模板】[UOJ#34]多项式乘法

原根和单位复根差不多,可以看做绕着p的剩余系绕了一圈,代码和FFT类似。
uoj #34 多项式乘法

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define MOD 998244353
#define G 3
int n,m,N,a[MAXN*3+10],b[MAXN*3+10];
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
void read(){
    Read(n),Read(m);
    int i;
    for(i=0;i<=n;i++)
        Read(a[i]);
    for(i=0;i<=m;i++)
        Read(b[i]);
    for(N=1;N<=m+n;N<<=1);
}
int quick_pow(int a,int b){
    int ret(1);
    while(b){
        if(b&1)
            ret=1ll*ret*a%MOD;
        a=1ll*a*a%MOD;
        b>>=1;
    }
    return ret;
}
void ntt(int *a,int N,int f){
    int i,j=0,t,k;
    for(i=1;i<N-1;i++){
        for(t=N;j^=t>>=1,~j&t;);
        if(i<j){
            swap(a[i],a[j]);
        }
    }
    for(i=1;i<N;i<<=1){
        t=i<<1;
        int wn=quick_pow(G,(MOD-1)/t);
        for(j=0;j<N;j+=t){
            int w=1;
            for(k=0;k<i;k++,w=1ll*w*wn%MOD){
                int x=a[j+k],y=1ll*w*a[j+k+i]%MOD;
                a[j+k]=(x+y)%MOD,a[j+k+i]=(x-y+MOD)%MOD;
            }
        }
    }
    if(f==-1){
        reverse(a+1,a+N);
        int inv=quick_pow(N,MOD-2);
        for(i=0;i<N;i++)
            a[i]=1ll*a[i]*inv%MOD;
    }
}
void solve(){
    ntt(a,N,1);
    ntt(b,N,1);
    int i;
    for(i=0;i<N;i++)
        a[i]=1ll*a[i]*b[i]%MOD;
    ntt(a,N,-1);
}
void print(){
    for(int i=0;i<n+m;i++)
        printf("%d ",a[i]);
    printf("%d\n",a[n+m]);
}
int main()
{
    read();
    solve();
    print();
}
posted @ 2016-06-19 00:38  outer_form  阅读(188)  评论(0编辑  收藏  举报