首页 > 其他 > 详细

【模板】多项式求逆

时间:2019-03-22 10:44:21      阅读:162      评论:0      收藏:0      [点我收藏+]

题目

要求出满足\(F(x)?G(x)≡1 (mod x^n)\)
假设已知\(F(x)*H(x) ≡1 (mod x^\lceil \frac{n}{2} \rceil)\)
\(F(x)*G(x) ≡1 (mod x^\lceil \frac{n}{2} \rceil)\)
所以\(F(x)*(G(x)-H(x)) ≡ 0 (mod x^\lceil \frac{n}{2} \rceil)\)
两边平方\(G(x)^2+H(x)^2-2G(x)H(x) ≡ 0 (mod x^n)\)
两边同时乘F(x) \(F(x)G(x)^2+H(x)^2F(x)-2F(x)G(x)H(x) ≡ 0 (mod x^n)\)
可得\(G(x) ≡ 2H(x)-H(x)^2*F(x) (mod x^n)\)
然后用NTT做多项式乘法...
因为第一次写这个,而且NTT也不是很熟练,所以是连写带贺的QWQ过段时间再来重构

#include <bits/stdc++.h>
using namespace std;
const int Mo = 998244353;
const int MAXN = 2100000;
int n, a[MAXN], b[MAXN], d[MAXN], rev[MAXN];
inline int read() {
    char ch; bool f = false; int res = 0;
    while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
    if (ch == '-') f = true; else res = ch - '0';
    while ((ch = getchar()) >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0';
    return f? ~res + 1 : res;
}
inline int ksm (int x, int y) {
    int sum = 1;
    for (; y; ) {
        if (y & 1)
            sum = 1LL * sum * x % Mo;
            y >>= 1;
            x = 1LL * x * x % Mo; 
    }
    return sum;
}
void NTT (int *a, int n, int x){
    for (int i = 0; i < n; ++ i) 
        if (i < rev[i])
            swap(a[i], a[rev[i]]);
    for (int i = 1; i < n; i <<= 1) {
        int y = ksm(3, (Mo - 1) / (i << 1));
        for (int j = 0; j < n; j += (i << 1)) {
            int x1, x2, x3 = 1;
            for (int k = 0; k < i; ++ k, x3 = 1LL * x3 * y % Mo) {
                x1 = a[j + k];
                x2 = 1LL * x3 * a[j + k + i] % Mo;
                a[j + k] = (x1 + x2) % Mo;
                a[j + k + i] = (x1 - x2 + Mo) % Mo;
            }
        }
    }
    if (x == 1) 
        return;
    int z = ksm(n, Mo - 2);
    reverse(a + 1, a + n);
    for (int i = 0; i < n; ++ i)
        a[i] = 1LL * a[i] * z % Mo;
}
void work (int c, int *a, int *b) {
    if (c == 1) {
        b[0] = ksm(a[0], Mo - 2);
        return;
    }
    work((c + 1) >> 1, a, b);
    int len = 0, x = 1;
    while (x < (c << 1))
        x <<= 1, ++ len;
    for (int i = 1; i < x; ++ i) 
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
    for (int i = 0; i < c; ++ i)
        d[i] = a[i];
    for (int i = c; i < x; ++ i)
        d[i] = 0;
    NTT(d, x, 1);
    NTT(b, x, 1);
    for (int i = 0; i < x; ++ i)
        b[i] = 1LL * (2 - 1LL * d[i] * b[i] % Mo + Mo) % Mo * b[i] % Mo;
    NTT(b, x, -1);
    for (int i = c; i < x; ++ i)
        b[i] = 0;   
}
int main() {
    n = read();
    for (int i = 0; i < n; ++ i)
        a[i] = read();
    work(n, a, b);
    for (int i = 0; i < n; ++ i)
        printf("%d ", b[i]);
    return 0;
}

【模板】多项式求逆

原文:https://www.cnblogs.com/wjnclln/p/10576231.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!