UOJ#34. 多项式乘法(NTT)

Posted 自为

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ#34. 多项式乘法(NTT)相关的知识,希望对你有一定的参考价值。

这是一道模板题。

给你两个多项式,请输出乘起来后的多项式。

输入格式

第一行两个整数 nn 和 mm,分别表示两个多项式的次数。

第二行 n+1n+1 个整数,表示第一个多项式的 00 到 nn 次项系数。

第三行 m+1m+1 个整数,表示第二个多项式的 00 到 mm 次项系数。

输出格式

一行 n+m+1n+m+1 个整数,表示乘起来后的多项式的 00 到 n+mn+m 次项系数。

样例一

input

1 2
1 2
1 2 1

output

1 4 5 2

explanation

(1+2x)(1+2x+x2)=1+4x+5x2+2x3(1+2x)⋅(1+2x+x2)=1+4x+5x2+2x3。

限制与约定

0n,m1050≤n,m≤105,保证输入中的系数大于等于 00 且小于等于 99。

时间限制1s1s

空间限制256MB

 

震惊!

TLE一上午的原因竟然是素数和原根的定义没有加const!

NTT的板子题

把单位元换成原根就好

#include<cstdio>
#include<algorithm>
#include<cmath>
#define swap(x,y) x ^= y, y ^= x, x ^= y
#define LL long long 
using namespace std;
const int MAXN = 3 * 1e6 + 10;
inline int read(){
    int x=0,f=1;char ch= ;
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9)x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int N, M, limit = 1, L;
const int P = 998244353, G = 3, Gi = 332748118; 
LL a[MAXN], b[MAXN];
int r[MAXN];
inline LL fastpow(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;
}
inline void NTT(LL *A, int type) {
    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) {    
        LL Wn = fastpow( type == 1 ? G : Gi , (P - 1) / (mid << 1));
        for(int j = 0; j < limit; j += (mid << 1)) {
            LL w = 1;
            for(int k = 0; k < mid; k++, w = (w * Wn) % P) {
                 int x = A[j + k], y = w * A[j + k + mid] % P;
                 A[j + k] = (x + y) % P,
                 A[j + k + mid] = (x - y + P) % P;
            }
        }
    }
}
int main() {
    #ifdef WIN32
    freopen("a.in", "r", stdin);
    #endif
    N = read(); M = read();
    for(int i = 0; i <= N; i++) a[i] = (read() + P) % P;
    for(int i = 0; i <= M; i++) b[i] = (read() + P) % P;
    while(limit <= N + M) limit <<= 1, L++;
    for(int i = 0; i < limit; i++)
        r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));    
    NTT(a, 1);NTT(b, 1);    
    for(int i = 0; i < limit; i++) a[i] = (a[i] * b[i]) % P;
    NTT(a, -1);    
    LL inv = fastpow(limit, P - 2);
    for(int i = 0; i <= N + M; i++)
        printf("%d ", (a[i] * inv) % P);
    return 0;
}

 

以上是关于UOJ#34. 多项式乘法(NTT)的主要内容,如果未能解决你的问题,请参考以下文章

uoj#34. 多项式乘法

uoj34 多项式乘法

●UOJ 34 多项式乘法

UOJ #34. 多项式乘法

[UOJ 34]多项式乘法

[uoj#34] [洛谷P3803] 多项式乘法(FFT)