zoukankan      html  css  js  c++  java
  • 洛谷P4245 【模板】MTT(任意模数NTT)

    题目背景

    模板题,无背景

    题目描述

    给定 22 个多项式 F(x), G(x)F(x),G(x) ,请求出 F(x) * G(x)F(x)G(x) 。

    系数对 pp 取模,且不保证 pp 可以分解成 p = a cdot 2^k + 1p=a2k+1 之形式。

    输入输出格式

    输入格式:

    输入共 33 行。
    第一行 33 个整数 n, m, pn,m,p ,分别表示 F(x), G(x)F(x),G(x) 的次数以及模数 pp 。
    第二行为 n+1n+1 个整数, 第 ii 个整数 a_iai 表示 F(x)F(x) 的 i-1i1 次项的系数。
    第三行为 m+1m+1 个整数, 第 ii 个整数 b_ibi 表示 G(x)G(x) 的 i-1i1 次项的系数。

    输出格式:

    输出 n+m+1n+m+1 个整数, 第 ii 个整数 c_ici 表示 F(x) * G(x)F(x)G(x) 的 i-1i1 次项的系数。

    输入输出样例

    输入样例#1: 复制
    5 8 28
    19 32 0 182 99 95
    77 54 15 3 98 66 21 20 38
    输出样例#1: 复制
    7 18 25 19 5 13 12 2 9 22 5 27 6 26

    说明

    1 leq n leq 10^5, 0 leq a_i, b_i leq 10^9, 2 leq p leq 10^9 + 91n105,0ai,bi109,2p109+9

    MTT不会,

    只好用三模数NTT搞

    板子题

    原理可以看这里

    真TM恶心。。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++)
    #define swap(x,y) x ^= y, y ^= x, x ^= y
    #define LL long long 
    const int MAXN = 3 * 1e6 + 10;
    using namespace std;
    char buf[1<<21], *p1 = buf, *p2 = buf;
    inline int read() { 
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int P1 = 469762049, P2 = 998244353, P3 = 1004535809, g = 3; 
    const LL PP = 1ll * P1 * P2;
    int N, M, P, limit = 1, L;
    int A[MAXN], B[MAXN], C[MAXN], D[MAXN], Ans[3][MAXN], r[MAXN];
    LL fastmul(LL a, LL b, LL mod) {
        a %= mod, b %= mod;
        return ((a * b - (LL)((LL)((long double)a / mod * b + 1e-3) * mod)) % mod + mod) % mod;
    }
    int fastpow(int a, int p, int mod) {
        int base = 1;
        while(p) {
            if(p & 1) base = 1ll * a * base % mod;
            a = 1ll * a * a % mod; p >>= 1;
        }
        return base % mod;
    } 
    void NTT(int *A, const int n, const int type, const int mod) {
        for(int i = 0; i < n; i++)
            if(i < r[i]) swap(A[i], A[r[i]]);
        for(int mid = 1; mid < n; mid <<= 1) {
            int W = fastpow(type == 1 ? g : fastpow(g, mod - 2, mod) , (mod - 1) / (mid << 1), mod);
            for(int j = 0; j < n; j += (mid << 1)) {
                int w = 1;
                for(int k = 0; k <mid; k++, w = 1ll * w * W % mod) {
                    int x = A[j + k], y = 1ll * w * A[j + k + mid] % mod;
                    A[j + k] = (x + y) % mod,
                    A[j + k + mid] = (x - y + mod) % mod;
                }
            }
        }
        if(type == -1) {
            int inv = fastpow(n, mod - 2, mod);
            for(int i = 0; i < n; i++) 
                A[i] = 1ll * A[i] * inv % mod;
        }
    }
    
    int main() {
        #ifdef WIN32
        freopen("a.in", "r", stdin);
        #endif
        N = read(), M = read(), P = read();
        for(int i = 0; i <= N; i++) A[i] = read();
        for(int i = 0; i <= M; i++) B[i] = read();
        
        while(limit <= N + M) limit <<= 1, L++;
        for(int i = 0; i <= limit; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
        
        copy(A, A + N + 1, C); copy(B, B + M + 1, D);
        NTT(C, limit, 1, P1); NTT(D, limit, 1, P1);
        for(int i = 0; i <= limit; i++) Ans[0][i] = 1ll * C[i] * D[i] % P1;
        
        memset(C, 0, sizeof(C)); memset(D, 0, sizeof(D));
        copy(A, A + N + 1, C); copy(B, B + M + 1, D);
        NTT(C, limit, 1, P2); NTT(D, limit, 1, P2);
        for(int i = 0; i <= limit; i++) Ans[1][i] = 1ll * C[i] * D[i] % P2;
        
        memset(C, 0, sizeof(C)); memset(D, 0, sizeof(D));
        copy(A, A + N + 1, C); copy(B, B + M + 1, D);
        NTT(C, limit, 1, P3); NTT(D, limit, 1, P3);
        for(int i = 0; i <= limit; i++) Ans[2][i] = 1ll * C[i] * D[i] % P3;
        
        NTT(Ans[0], limit, -1, P1);
        NTT(Ans[1], limit, -1, P2);
        NTT(Ans[2], limit, -1, P3);
        
        for(int i = 0; i <= N + M; i++) {
            LL A = (fastmul(1ll * Ans[0][i] * P2 % PP, fastpow(P2 % P1, P1 - 2, P1), PP) + 
                    fastmul(1ll * Ans[1][i] * P1 % PP, fastpow(P1 % P2, P2 - 2, P2), PP) ) % PP;
            LL K = ((Ans[2][i] - A) % P3 + P3) % P3 * fastpow(PP % P3, P3 - 2, P3) % P3;
            printf("%d ",(A % P + ((K % P) * (PP % P)) % P ) % P);         
        }
        return 0;
    }
  • 相关阅读:
    java中栈内存和堆内存的简单理解
    java中构造函数与一般函数的区别

    另一部漫画
    海边的卡夫卡
    11-12
    这篇大概值一百万吧
    我的千岁寒
    11-9
    嗯……………股票已经涨的我不想上班了
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8982560.html
Copyright © 2011-2022 走看看