放个NTT模板

常用素数及其原根

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>

typedef long long LL;
const LL mod = 998244353;
int N, M;
LL a[100005], b[100005], c[100005], g;

LL qpower(LL, LL);
LL inline inv(LL x) { return qpower(x, mod - 2); }
void NTT(LL *, int, int);
int main() {
    std::cin >> N >> M;
    for (int i = 0; i < N; ++i) std::cin >> a[i];
    for (int i = 0; i < M; ++i) std::cin >> b[i];
    int sz = 1;
    g = 3;
    while (sz < N + M) sz <<= 1;
    NTT(a, sz, 1);
    NTT(b, sz, 1);
    for (int i = 0; i < sz; ++i)
        c[i] = a[i] * b[i] % mod;
    NTT(c, sz, -1);
    for (int i = 0; i < N + M - 1; ++i)
        std::cout << c[i] << " ";
        
    return 0;
}
LL qpower(LL x, LL y) {
    LL res = 1;
    while (y) {
        if (y & 1) (res *= x) %= mod;
        (x *= x) %= mod;
        y >>= 1;
    }
    return res;
}
void NTT(LL *arr, int size, int type) {
    int rev[100005];
    rev[0] = 0;
    for (int i = 1; i < size; ++i)
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (size >> 1) : 0);
    for (int i = 0; i < size; ++i)
        if (rev[i] > i) std::swap(arr[i], arr[rev[i]]);
    for (int len = 2; len <= size; len <<= 1) {
        LL wn = qpower(g, (mod - 1) / len);
        if (type == -1) wn = inv(wn);
        for (int i = 0; i < size; i += len) {
            LL w = 1;
            for (int j = 0; j < (len >> 1); ++j, w = w * wn % mod) {
                LL tmp1 = arr[i + j], tmp2 = arr[i + (len >> 1) + j] * w % mod;
                arr[i + j] = tmp1 + tmp2;
                arr[i + j + (len >> 1)] = tmp1 - tmp2;
                if (arr[i + j] >= mod) arr[i + j] -= mod;
                if (arr[i + j + (len >> 1)] < 0) arr[i + j + (len >> 1)] += mod;
            }
        }
    }
    if (type == -1) {
        LL t = inv(size);
        for (int i = 0; i < size; ++i)
            arr[i] = arr[i] * t % mod;
    }
}
//Rhein_E

猜你喜欢

转载自www.cnblogs.com/Rhein-E/p/10432783.html
NTT