zoukankan      html  css  js  c++  java
  • Luogu 4512 【模板】多项式除法

    高级操作,感觉非常神仙。

    题目中的字母太难懂了,重新定义一下。

    $$A(x) = B(x) * C(x) + D(x)$$

    其中,$A(x)$的次数是$n$,$B(x)$的次数是$m$,$A, B$都已知,要求$C$的次数是$n - m$,$D$的次数小于$m$。

    定义一种操作:

    如果$A$的次数为$n$,那么

    $$A_R(x) = x^nA(frac{1}{x})$$

    其实就是把一个多项式各项系数翻转过来。

    比如$A(x) = x^3 + 2x^2 + 3x + 5$,有

    $$A_R(x) = 5x^3 + 3x^2 + 2x + 1$$

    有了这个操作之后就可以变魔术了。

    发现这个$D(x)$很难受,想办法把它搞掉。

    $$A(x) = B(x) * C(x) + D(x)$$

    $$A(frac{1}{x}) = B(frac{1}{x})C(frac{1}{x}) + D(frac{1}{x})$$

    两边乘上$x^n$,

    $$x^nA(frac{1}{x}) = x^mB(frac{1}{x})x^{n - m}C(frac{1}{x}) + x^{n - m + 1} * x^{m - 1}D(frac{1}{x})$$

    $$A_R(x) = B_R(x)C_R(x) + x^{n - m + 1} D_R(x)$$

    两边模上$x^{n - m + 1}$,

    $$A_R(x) equiv B_R(x)C_R(x) (mod x^{n - m + 1}) $$

    其实就是求逆了呀。

    求出$C(x)$之后只要重新算一遍多项式乘法减掉就可以算出$D(x)$了。

    时间复杂度$O(nlogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef vector <ll> poly;
    
    const int N = 1e5 + 5;
    
    namespace Poly {
        const int L = 1 << 18;
        const ll P = 998244353LL;
        
        int lim, pos[L];
        
        inline void deb(poly c) {
            for (int i = 0; i < (int)c.size(); i++)
                printf("%lld%c", c[i], " 
    "[i == (int)c.size() - 1]);
        }
        
        template <typename T>
        inline void inc(T &x, T y) {
            x += y;
            if (x >= P) x -= P;
        }
        
        template <typename T>
        inline void sub(T &x, T y) {
            x -= y;
            if (x < 0) x += P;
        }
        
        inline ll fpow(ll x, ll y) {
            ll res = 1;
            for (; y > 0; y >>= 1) {
                if (y & 1) res = res * x % P;
                x = x * x % P;
            }
            return res;
        }
        
        inline void prework(int len) {
            int l = 0;
            for (lim = 1; lim < len; lim <<= 1, ++l);
            for (int i = 0; i < lim; i++)
                pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (l - 1));
        }
        
        inline void ntt(poly &c, int opt) {
            c.resize(lim, 0);
            for (int i = 0; i < lim; i++)
                if (i < pos[i]) swap(c[i], c[pos[i]]);
            for (int i = 1; i < lim; i <<= 1)  {
                ll wn = fpow(3, (P - 1) / (i << 1));
                if (opt == -1) wn = fpow(wn, P - 2);
                for (int len = i << 1, j = 0; j < lim; j += len) {
                    ll w = 1;
                    for (int k = 0; k < i; k++, w = w * wn % P) {
                        ll x = c[j + k], y = w * c[j + k + i] % P;
                        c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P; 
                    }
                }
            }
            
            if (opt == -1) {
                ll inv = fpow(lim, P - 2);
                for (int i = 0; i < lim; i++) c[i] = c[i] * inv % P;
            }
        }
        
        inline poly mul(const poly x, const poly y) {
            poly u = x, v = y, res;
            prework(x.size() + y.size() - 1);
            ntt(u, 1), ntt(v, 1);
            for (int i = 0; i < lim; i++) res.push_back(u[i] * v[i] % P);
            ntt(res, -1);
            res.resize(x.size() + y.size() - 1);
            return res;
        }
        
        poly getInv(poly x, int len) {
            x.resize(len, 0);
            if (len == 1) {
                poly res;
                res.push_back(fpow(x[0], P - 2));
                return res;
            }
            
            poly y = getInv(x, (len + 1) >> 1);
            
            prework(len << 1);
            poly u = x, v = y, res;
            ntt(u, 1), ntt(v, 1);
            for (int i = 0; i < lim; i++) res.push_back(v[i] * ((2LL - u[i] * v[i] % P + P) % P) % P);
            ntt(res, -1);
            
            res.resize(len, 0);
            return res;
        }
        
        inline poly getDiv(poly x, poly y) {
            poly u = x, v = y, res;
            
            reverse(u.begin(), u.end());
            reverse(v.begin(), v.end());    
    //        deb(u), deb(v);
            
            int len = x.size() - y.size() + 1;
            u.resize(len, 0), v.resize(len, 0);
            
    //        deb(u), deb(v);
            
            res = getInv(v, len);
            
    //        deb(res);
            
            res = mul(u, res);
            res.resize(len);
    //        deb(u);
            
            reverse(res.begin(), res.end());
            
            return res;
        }
        
        inline poly getRest(poly x, poly y) {
            poly u = x, v = y, res = getDiv(x, y);
            
            v = mul(v, res);
            res = u;
            int len = max(u.size(), v.size());
            res.resize(len, 0), v.resize(len, 0);
            for (int i = 0; i < len; i++) res[i] = (res[i] - v[i] + P) % P;
            
            for (; !res.empty() && !res[res.size() - 1]; res.pop_back());
            return res;
        }
        
    }
    
    using Poly :: getDiv;
    using Poly :: getRest;
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for (; ch > '9'|| ch < '0'; ch = getchar())
            if (ch == '-') op = -1;
        for (; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    int main() {
        int n, m;
        read(n), read(m);
        ++n, ++m;
        
        poly x, y;
        x.resize(n, 0), y.resize(m, 0);
        for (int i = 0; i < n; i++) read(x[i]);
        for (int i = 0; i < m; i++) read(y[i]);
        
        poly u = getDiv(x, y), v = getRest(x, y);
        for (int i = 0; i < (int)u.size(); i++)
            printf("%lld%c", u[i], " 
    "[i == (int)u.size() - 1]);
        for (int i = 0; i < (int)v.size(); i++) 
            printf("%lld%c", v[i], " 
    "[i == (int)v.size() - 1]);
        
        return 0;
    }
    View Code
  • 相关阅读:
    hdu2328 Corporate Identity
    hdu1238 Substrings
    hdu4300 Clairewd’s message
    hdu3336 Count the string
    hdu2597 Simpsons’ Hidden Talents
    poj3080 Blue Jeans
    poj2752 Seek the Name, Seek the Fame
    poj2406 Power Strings
    hust1010 The Minimum Length
    hdu1358 Period
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/10322908.html
Copyright © 2011-2022 走看看