zoukankan      html  css  js  c++  java
  • [洛谷P4238] 多项式乘法逆

    给定 (n-1) 次多项式 (F(x)=sum_{i=0}^{n-1}a_ix^i),求出多项式 (G(x)=sum_{i=0}^{n-1}b_ix^i),使得 (F(x)*G(x)equiv 1pmod{x^n}),系数对 (998244353) 取模。((1leq nleq 10^5,0leq a_ileq 10^9))

    题解

    如果 (F(x)=a_0), 只有常数项,显然 (G(x)=a_0^{-1})
    (H(x)equiv G(x)pmod{x^{lceilfrac{2}{n} ceil}}),则有

    [F(x)*H(x)equiv 1 pmod{x^{lceilfrac{2}{n} ceil}}\ F(x)*G(x)equiv 1 pmod{x^{lceilfrac{2}{n} ceil}}\ F(x)*(H(x)-G(x))equiv 0 pmod{x^{lceilfrac{2}{n} ceil}}\ H(x)-G(x)equiv 0 pmod{x^{lceilfrac{2}{n} ceil}}\ H^2(x)-2H(x)*G(x)+G^2(x)equiv 0 pmod{x^n}\ F(x)*H^2(x)-2H(x)+G(x)equiv 0 pmod{x^n}\ G(x)equiv H(x)*(2-F(x)*H(x)) pmod{x^n} ]

    所以我们只需要进行倍增,每次做一下NTT即可。时间复杂度 (O(nlog n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType& T) {
        elemType X = 0, w = 0; char ch = 0;
        while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
        while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        T = (w ? -X : X);
    }
    
    inline LL ExPow(LL b, LL n, LL MOD) {
        if (MOD == 1) return 0;
        LL x = 1;
        LL Power = b % MOD;
        while (n) {
            if (n & 1) x = x * Power % MOD;
            Power = Power * Power % MOD;
            n >>= 1;
        }
        return x;
    }
    
    namespace Poly {
        int r[2100010];
        LL buf[2100010];
        int L, limit;
        const LL P = 998244353, G = 3, Gi = 332748118;
    
    
        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 = ExPow(type == 1 ? G : Gi, (P - 1) / (mid << 1), P);
                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;
                    }
                }
            }
            if (type == 1) return;
            LL inv_limit = ExPow(limit, P - 2, P);
            for (int i = 0; i < limit; ++i)
                A[i] = (A[i] * inv_limit) % P;
        }
    
        void PolyInv(LL* a, LL* inv, int N) {
            if (N == 1) { inv[0] = ExPow(a[0], P - 2, P);return; }
            PolyInv(a, inv, (N + 1) >> 1);
            for (limit = 1; limit <= (N << 1); limit <<= 1);
            for (int i = 0; i < limit; ++i) {
                r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (limit >> 1) : 0);
                buf[i] = (i < N ? a[i] : 0);
            }
            NTT(buf, 1);NTT(inv, 1);
            for (int i = 0; i < limit; ++i)
                inv[i] = (2LL - buf[i] * inv[i] % P + P) % P * inv[i] % P;
            NTT(inv, -1);
            fill(inv + N, inv + limit, 0);
            return;
        }
    }
    LL a[2100010], b[2100010];
    int n, m;
    
    int main() {
        Read(n);
        for (int i = 0;i < n;++i)
            Read(a[i]);
        Poly::PolyInv(a, b, n);
        for (int i = 0;i < n;++i)
            printf("%lld ", b[i]);
        printf("
    ");
    
        return 0;
    }
    
  • 相关阅读:
    JDK Integer.reverse 算法实现分析
    HomeBrew更新
    时序数据简介
    MQTT协议简析
    Maven+Spring Profile实现生产环境和开发环境的切换
    Thread与Runnable的一个小陷阱
    HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash
    该不该在C#中使用var关键词
    疑难问题解决备忘录(3)——ubuntu12.04配置vsftp本地用户登录
    疑难问题解决备忘录(2)——ubuntu12.04分配swap
  • 原文地址:https://www.cnblogs.com/AEMShana/p/14492081.html
Copyright © 2011-2022 走看看