NTT板子 -- from ACdreamer -- test by HDU6061

NTT板子

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int MAXN = 400040;
typedef long long LL;

const int N = 100005;
const int P = 998244353;
const LL MOD = 998244353;
const int G = 3;
const int NUM = 25;
LL x1[MAXN];
LL x2[MAXN];
LL c[MAXN/4];
LL ans[MAXN/4];
LL  wn[NUM];

LL quick_mod(LL a, LL b, LL m)
{
    LL ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % m;
            b--;
        }
        b >>= 1;
        a = a * a % m;
    }
    return ans;
}

void GetWn()
{
    for(int i=0; i<NUM; i++)
    {
        int t = 1 << i;
        wn[i] = quick_mod(G, (P - 1) / t, P);
    }
}
void Rader(LL a[], int len)
{
    int j = len >> 1;
    for(int i=1; i<len-1; i++)
    {
        if(i < j) swap(a[i], a[j]);
        int k = len >> 1;
        while(j >= k)
        {
            j -= k;
            k >>= 1;
        }
        if(j < k) j += k;
    }
}

void NTT(LL a[], int len, int on)
{
    Rader(a, len);
    int id = 0;
    for(int h = 2; h <= len; h <<= 1)
    {
        id++;
        for(int j = 0; j < len; j += h)
        {
            LL w = 1;
            for(int k = j; k < j + h / 2; k++)
            {
                LL u = a[k] % P;
                LL t = w * (a[k + h / 2] % P) % P;
                a[k] = (u + t) % P;
                a[k + h / 2] = ((u - t) % P + P) % P;
                w = w * wn[id] % P;
            }
        }
    }
    if(on == -1)
    {
        for(int i = 1; i < len / 2; i++)
            swap(a[i], a[len - i]);
        LL Inv = quick_mod(len, P - 2, P);
        for(int i = 0; i < len; i++)
            a[i] = a[i] % P * Inv % P;
    }
}

void Conv(LL a[], LL b[], int n)
{
    NTT(a, n, 1);
    NTT(b, n, 1);
    for(int i = 0; i < n; i++)
        a[i] = a[i] * b[i] % P;
    NTT(a, n, -1);
}
const int tN = 800000 + 5;
long long F[tN], Finv[tN], inv[tN];//Fê&#199;&#189;×3&#203;£&#172;Finvê&#199;&#196;&#230;&#212;aμ&#196;&#189;×3&#203;
void init(){
    inv[1] = 1;
    for(long long  i = 2; i < tN; i ++){
        inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
    }
    F[0] = Finv[0] = 1;
    for(long long i = 1; i < tN; i ++){
        F[i] = F[i-1] * 1ll * i % MOD;
        Finv[i] = Finv[i-1] * 1ll * inv[i] % MOD;
    }
}
int main()
{
    GetWn();
    init();
    int n,m;
    while (~scanf("%d",&n)){
        for (int i = 0; i<=n; i++){
            scanf("%I64d",&c[i]);
        }
        scanf("%d",&m);
        long long suma = 0;
        for (int i = 1;i<=m;i++){
            long long a;
            scanf("%I64d",&a);
            suma = (suma - a+MOD) % MOD;
        }

        int len1 = n+1;
        int len = 1;
        while ( len < 2*len1 ) len <<= 1;

        for (int i = 0; i<len1 ; i++)
            x1[i] = c[n-i]*F[n-i]%MOD;
        for (int i = len1 ; i < len ;i++)
            x1[i] = 0;
        long long po = 1;
        for (int i = 0; i<len1 ; i++){
            x2[i] = po*Finv[i]%MOD;
            po = ((po*suma) % MOD + MOD) % MOD;
        }
        for (int i = len1 ; i < len ;i++)
            x2[i] = 0;
        Conv(x1, x2, len);

        for (int i = 0 ; i<=n ; i++)
            ans[n-i] = (long long) (x1[i] + 0.5 ) % MOD;
        if (suma!=0)
        for (int i = 0;i<=n; i++)
            printf("%I64d ",(((ans[i]%MOD)*Finv[i])%MOD+MOD)%MOD);
        else
        for (int i = 0;i<=n; i++)
            printf("%I64d ",c[i]%MOD);
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/HITLJR/p/7418372.html