多项式板子

Posted luoyibujue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式板子相关的知识,希望对你有一定的参考价值。

不包含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;
}

 

以上是关于多项式板子的主要内容,如果未能解决你的问题,请参考以下文章

多项式板子·新

多项式板子(待补充)

全家福多项式的各种板子

uoj34 多项式乘法

FFT(板子)

FFT(板子)