zoukankan      html  css  js  c++  java
  • 多项式板子

    不包含MTT的板子, 这种有的话就弃疗了

    /*
    求逆迭代 B = 2B - AB^2
    
    系数反转 F(1 / x) * x ^ n
    
    除法迭代 已知 F(x) = Q(x) * G(x) + R(x) F(x),G(x) 求Q(x) R(x)
    
    F(x) = Q(x) * G(x) + R(x) mod x ^ {n + 1}
    
    F(1 / x) = Q(1 / x) * G(1 / x) + R(1 / x) mod x ^ {n + 1}
    
    Frev(x) = Qrev(x) * Grev(x) + Rrev(x) x ^(n - du_R) mod x ^ n + 1
    
    deg_Q = n + m Deg_R < m
    则 (n - dU_R > n - m)
    
    F(x) = Q(x) * G(x) +  mod x ^ {n - m + 1}
    
    然后求逆算出Q, 余数减去即可
    
    多项式求导和积分 非常简单
    
    多项式求ln 基本求导法则
    
    G(x) = Ln(F(x))
    G(x)' = Ln(F(x))' F(x)' = F(x)' / F(x)
    没了
    
    多项式exp
    
    F(x) = e ^ (A(x))
    
    ln(F(x)) - A(x) = 0
    
    折G(x) = (ln(F(x)) - A(x))
    则
    F(x) = F0(x) - (G(F0(x)) / G'(F0_(x))
    = F0(x) -  (Ln(F0(x)) - A(x)) * F0(x)
    = F0(x) (1 - ln(F0(x)) + A(x))
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define mmp make_pair
    using namespace std;
    int read() {
        int nm = 0, f = 1;
        char c = getchar();
        for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
        return nm * f;
    }
    const int M = (1 << 20) + 5;
    const int  mod = 998244353;
    int add(int a, int b) {
        a += b;
        a -= a >= mod ? mod : 0;
        a += a < 0  ? mod : 0;
        return a;
    }
    
    int mul(int a, int b) {
        return 1ll * a * b % mod;
    }
    
    int poww(int a, int b) {
        int ans = 1, tmp = a;
        for(; b; b >>= 1, tmp = mul(tmp, tmp)) if(b & 1) ans = mul(ans, tmp);
        return ans;
    }
    
    namespace Poly {
        const int g = 3;
        int n;
        int pw[M], rw[M];
        void getw() {
            for(int i = 1; i <= M; i <<= 1) {
                pw[i] = poww(g, (mod - 1) / 2 / i);
                rw[i] = poww(pw[i], mod - 2);
            }
        }
    
        void init(int m) {
            n = m;
            while(n > (n & -n)) n += (n & -n);
        }
    
        void fft(int *x, int dft) {
            for(int i = 0, j = 0; i < n; i++) {
                if(i < j) swap(x[i], x[j]);
                for(int l = n >> 1; (j ^= l) < l; l >>= 1);
            }
            for(int step = 1; step < n; step <<= 1) {
                int wn = (dft == 1) ? pw[step] : rw[step];
                for(int i = 0; i < n; i += step << 1) {
                    int wnk = 1;
                    for(int j = i; j < i + step; j++) {
                        int a = x[j], b = mul(wnk, x[j + step]);
                        x[j] = add(a, b);
                        x[j + step] = add(a, -b);
                        wnk = mul(wnk, wn);
                    }
                }
            }
            if(dft == -1) {
                int invn = poww(n, mod - 2);
                for(int i = 0; i < n; i++) x[i] = mul(x[i], invn);
            }
        }
    
        void pcpy(int *x, int a, int *y, int b) {
            for(int i = 0; i < a; i++) {
                x[i] = (i < b) ? y[i] : 0;
            }
        }
    
        void pmul(int *x, int a, int *y, int b, int *z) {
            static int tx[M + 5], ty[M + 5];
    
            init(a + b - 1);
            pcpy(tx, n, x, a);
            pcpy(ty, n, y, b);
            fft(tx, 1), fft(ty, 1);
            for(int i = 0; i < n; i++) {
                tx[i] = mul(tx[i], ty[i]);
            }
            fft(tx, -1);
            for(int i = 0; i < a + b - 1; i++) {
                z[i] = tx[i];
            }
        }
    
        void pinv(int *x, int m, int *y) {
            static int tx[M + 5], ty[M + 5];
            if(m == 1) {
                y[0] = poww(x[0], mod - 2);
                return;
            }
            pinv(x, (m + 1) >> 1, y);
    
            init(m << 1);
            pcpy(tx, n, x, m);
            pcpy(ty, n, y, (m + 1) >> 1);
    
            fft(tx, 1), fft(ty, 1);
            for(int i = 0; i < n; i++) {
                tx[i] = 1ll * (2ll - 1ll * tx[i] * ty[i] % mod + mod) * ty[i] % mod;
            }
    
            fft(tx, -1);
    
            for(int i = 0; i < m; i++) {
                y[i] = tx[i];
            }
        }
    
        void prev(int *x, int m, int *y) {
            for(int i = 0; i < m; i++) y[i] = x[m - 1 - i];
        }
    
        void pdiv(int *x, int a, int *y, int b, int *z) {
            static int tx[M + 5], ty[M + 5], tz[M + 5];
    
            prev(x, a, tx);
            prev(y, b, ty);
    
            for(int i = b; i < a - b + 1; ++i) ty[i] = 0;
    
            pinv(ty, a - b + 1, tz);
            pmul(tx, a - b + 1, tz, a - b + 1, ty);
            prev(ty, a - b + 1, z);
        }
    
        void pmod(int *x, int a, int *y, int b, int *z) {
            static int tx[M + 5];
    
            if(a < b) {
                for(int i = 0; i < a; i++) {
                    z[i] = x[i];
                }
                return;
            }
    
            pdiv(x, a, y, b, tx);
            pmul(tx, a - b + 1, y, b, tx);
            for(int i = 0; i < b; i++) {
                z[i] = (x[i] - tx[i] + mod) % mod;
            }
        }
    
        void der(int *x, int m, int *y) {
            for(int i = 1; i < m; i++) y[i - 1] = 1ll * i * x[i] % mod;
            y[n - 1] = 0;
        }
    
        void inte(int *x, int m, int *y) {
            for(int i = 1; i < m; i++) y[i] = 1ll * x[i - 1] * poww(i, mod - 2) % mod;
            y[0] = 0;
        }
    
        void ln(int *x, int m, int *y) {
            static int tx[M + 5], ty[M + 5], tz[M + 5];
            der(x, m, tx);
            pinv(x, m, ty);
            pmul(tx, m, ty, m, tz);
            inte(tz, m, y);
        }
    // F0(x) (1 - ln(F0(x)) + A(x))
    
        void exp(int *x, int m, int *y) {
            static int ta[M + 5], tb[M + 5], tc[M + 5];
            if(m == 1) {
                y[0] = 1;
                return;
            }
            exp(x, (m + 1) >> 1, y);
            pcpy(ta, m, y, (m + 1) >> 1);
            ln(ta, m, tb);
            for(int i = 0; i < m; i++) {
                tb[i] = add(x[i], -tb[i]);
            }
            tb[0] = add(tb[0], 1);
            pcpy(ta, (m + 1) >> 1, y, (m + 1) >> 1);
            pmul(ta, (m + 1) >> 1, tb, m, tc);
            pcpy(y, m, tc, m);
        }
    }
    
    
    int pool[M * 20], *cur = pool;
    
    struct poly {
        int *a, l;
        poly() {}
        poly(int x) {
            a = cur;
            cur += (l = x);
        }
        poly(int *b, int x) {
            a = cur, cur += (l = x);
            memcpy(a, b, sizeof (int) * l);
        }
    };
    
    poly operator * (const poly &a, const poly &b) {
        poly c(a.l + b.l - 1);
        Poly::pmul(a.a, a.l, b.a, b.l, c.a);
        return c;
    }
    
    poly operator % (const poly &a, const poly &b) {
        poly c(b.l - 1);
        Poly::pmod(a.a, a.l, b.a, b.l, c.a);
        return c;
    }
    
    poly operator / (const poly &a, const poly &b) {
        poly c(b.l - 1);
        Poly::pdiv(a.a, a.l, b.a, b.l, c.a);
        return c;
    }
    
    poly ln(poly x) {
        poly y(x.l);
        Poly::ln(x.a, x.l, y.a);
        return y;
    }
    
    poly exp_(poly x) {
        poly y(x.l);
        Poly::exp(x.a, x.l, y.a);
        return y;
    }
    
    int main() {
        Poly::getw();
        
        return 0;
    }
  • 相关阅读:
    算法学习算法复杂度
    算法学习冒泡排序和快速排序
    焦点管理
    数据结构学习链表、双向链表、循环链表
    数据结构学习数组、栈和队列
    数据结构学习集合
    数据结构学习字典和散列表
    (转)一个webservice的小demo
    堆栈详解
    JS实现大小写转换
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10504996.html
Copyright © 2011-2022 走看看