【模板】多项式乘法 NTT

【模板】多项式乘法 NTT

Code:

#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define maxn 2000010
#define MOD 998244353 
#define mod MOD 
#define G 3 
#define setIO(s) freopen(s".in","r",stdin) 
#define ll long long
#define LL long long
#define P MOD
using namespace std;
int rev[maxn],len=1,n,m;
long long A[maxn],B[maxn],C[maxn];  
struct OPT {
    inline LL Pow(LL a, LL k) {
        LL base = 1;
        while(k) {
            if(k & 1) base = (base * a ) % P;
            a = (a * a) % P;
            k >>= 1;
        }
        return base % P;
    }
    void NTT(long long* a,int len,int opt){
        for(int i=0;i<len;i++){
            if(i<rev[i]){
                swap(a[i],a[rev[i]]);
            }
        }
        for(int i=1;i<len;i<<=1){
            long long wn=Pow(G,(opt*((MOD-1)/(i<<1))+MOD-1)%(MOD-1));
            int step=i<<1;
            for(int j=0;j<len;j+=step){
                long long w=1;
                for(int k=0;k<i;k++,w=(1ll*w*wn)%MOD){
                    long long x=a[j+k];
                    long long y=1ll*w*a[j+k+i]%MOD;
                    a[j+k]=(x+y)%MOD;
                    a[j+k+i]=(x-y+MOD)%MOD;
                }
            }
        }
        if(opt==-1){
            long long r=Pow(len,MOD-2);
            for(int i=0;i<len;i++)
                a[i]=1ll*a[i]*r%MOD;
        }
    }
}T;
int main(){
    //setIO("input");
    scanf("%d%d",&n,&m);
    int x,l=0; 
    for(int i=0;i<=n;++i) scanf("%lld",&A[i]);
    for(int i=0;i<=m;++i) scanf("%lld",&B[i]); 
    while(len<=n+m) len<<=1, ++l;
    for(int i=0;i<len;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    T.NTT(A,len,1),T.NTT(B,len,1); 
    for(int i=0;i<len;++i) C[i]=(LL)(A[i]*B[i])%MOD;
    T.NTT(C,len,-1);
    for(int i=0;i<=n+m;++i) printf("%d ",(C[i])%MOD);
    return 0;
}

  

posted @ 2019-01-30 10:33 EM-LGH 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值