多项式模板



模板1

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
 
const int MOD = 998244353;
 
inline int Add(int a, int b) {
    return (a + b >= MOD) ? (a + b - MOD) : (a + b);
}
inline int Sub(int a, int b) {
    return (a >= b) ? (a - b) : (a - b + MOD);
}
inline int Mul(int a, int b) {
    return (LL)a * b % MOD;
}
inline int Pow(int a, int b) {
    int c = 1;
    for (; b; a = Mul(a, a), b >>= 1)
        if (b & 1) c = Mul(c, a);
    return c;
}

namespace Poly {
 
    const int K = 20, N = 1 << K;
 
    int inv[N];
 
    void InitInv() {
        inv[1] = 1;
        for (int i = 2; i < N; ++i)
            inv[i] = Mul(Sub(0, MOD / i), inv[MOD % i]);
        return;
    }
    
    void Init(int k, int *w, int *rev) {
        int n = 1 << k;
        w[0] = 1;
        w[1] = Pow(3, (MOD - 1) / n);
        for (int i = 2; i < n; ++i)
            w[i] = Mul(w[i - 1], w[1]);
        rev[0] = 0;
        for (int i = 1; i < n; ++i)
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
        return;
    }
 
    void DFT(vector<int> &a, int k) {
        int n = 1 << k;
        static int _k = 0, _w[N * 2], _rev[N * 2];
        for (; _k <= k; ++_k) Init(_k, &_w[1 << _k], &_rev[1 << _k]);
        int *rev = &_rev[n];
        for (int i = 0; i < n; ++i)
            if (i < rev[i]) swap(a[i], a[rev[i]]);
        for (int l = 1; l <= k; ++l) {
            int m = 1 << (l - 1), *w = &_w[1 << l];
            for (vector<int> :: iterator p = a.begin(); p != a.begin() + n; p += m << 1)
                for (int i = 0; i < m; ++i) {
                    int t = Mul(p[i + m] , w[i]);
                    p[i + m] = Sub(p[i], t);
                    p[i] = Add(p[i], t);
                }
        }
        return;
    }
 
    void IDFT(vector<int> &a, int k) {
        DFT(a, k);
        int n = 1 << k, inv = Pow(n, MOD - 2);
        reverse(a.begin() + 1, a.begin() + n);
        for (int i = 0; i < n; ++i)
            a[i] = Mul(a[i], inv);
        return;
    }
 
    vector<int> Multiply(vector<int> a, vector<int> b) {
        int _n = (int)a.size() - 1, _m = (int)b.size() - 1, k = 0;
        for (; (1 << k) < _n + _m + 1; ++k);
        int n = 1 << k;
        a.resize(n);
        b.resize(n);
        DFT(a, k);
        DFT(b, k);
        for (int i = 0; i < n; ++i)
            a[i] = Mul(a[i], b[i]);
        IDFT(a, k);
        a.resize(_n + _m + 1);
        return a;
    }
 
    vector<int> Multiply_(vector<int> a, vector<int> b, int N) {
        int _n = (int)a.size() - 1, _m = (int)b.size() - 1, k = 0;
        for (; (1 << k) < _n + _m + 1; ++k);
        int n = 1 << k;
        a.resize(n);
        b.resize(n);
        DFT(a, k);
        DFT(b, k);
        for (int i = 0; i < n; ++i)
            a[i] = Mul(a[i], b[i]);
        IDFT(a, k);
        a.resize(N);
        return a;
    }
     
    vector<int> Addition(vector<int> a, vector<int> b) {
        if (a.size() < b.size()) swap(a, b);
        int m = (int)b.size() - 1;
        for (int i = 0; i <= m; ++i)
            a[i] = Add(a[i], b[i]);
        return a;
    }
 
    vector<int> Subtract(vector<int> a, vector<int> b) {
        if (a.size() < b.size()) a.resize(b.size());
        int m = (int)b.size() - 1;
        for (int i = 0; i <= m; ++i)
            a[i] = Sub(a[i], b[i]);
        return a;
    }
 
    vector<int> Inverse(vector<int> a) {
        if (!a[0]) {
            cerr << "can not inverse" << endl;
            throw;
        }
        int _n = (int)a.size();
        vector<int> b(1, Pow(a[0], MOD - 2)), c;
        for (int n = 1, k = 0; n < _n; ) {
            n <<= 1;
            ++k;
            b.resize(n << 1);
            c.resize(n << 1);
            for (int i = 0; i < n; ++i)
                c[i] = i < _n ? a[i] : 0;
            DFT(b, k + 1);
            DFT(c, k + 1);
            for (int i = 0; i < (n << 1); ++i)
                b[i] = Mul(b[i], Sub(2, Mul(b[i], c[i])));
            IDFT(b, k + 1);
            b.resize(n);
        }
        b.resize(_n);
        return b;
    }
    
    vector<int> De(vector<int> a) {
        int n = (int)a.size() - 1;
        for (int i = 0; i + 1 <= n; ++i)
            a[i] = Mul(a[i + 1], i + 1);
        return a;
    }
    
    vector<int> In(vector<int> a) {
        int n = (int)a.size() - 1;
        for (int i = n; i; --i)
            a[i] = Mul(a[i - 1], inv[i]);
        a[0] = 0;
        return a;
    }
     
    vector<int> Ln(vector<int> a) {
        if (a[0] != 1) {
            cerr << "can not ln" << endl;
            throw;
        }
        int n = (int)a.size();
        a = In(Multiply(De(a), Inverse(a)));
        a.resize(n);
        return a;
    }
 
    vector<int> Exp(vector<int> a) {
        if (a[0]) {
            cerr << "can not exp" << endl;
            throw;
        }
        int n = (int)a.size();
        vector<int> b(1, 1), c(1, a[0]);
        int k = 0;
        for (; (1 << k) < n; ) {
            ++k;
            b.resize(1 << k);
            c.resize(1 << k);
            for (int i = (1 << (k - 1)); i < (1 << k); ++i)
                c[i] = i < n ? a[i] : 0;
            b = Multiply(b, Subtract(Addition(vector<int>(1, 1), c), Ln(b)));
            b.resize(1 << k);
        }
        b.resize(n);
        return b;
    }
    
}

void Print(vector<int> a) {
    for (int i = 0; i < (int)a.size(); ++i)
        cerr << a[i] << ' ';
    cerr << endl;
    return;
}

int main() {
    Poly::InitInv();
    return 0;
}



模板2 拆系数FFT

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
 
const int MOD = 1E9 + 7;
 
inline int Add(int a, int b) {
    return (a + b >= MOD) ? (a + b - MOD) : (a + b);
}
inline int Sub(int a, int b) {
    return (a >= b) ? (a - b) : (a - b + MOD);
}
inline int Mul(int a, int b) {
    return LL(a) * b % MOD;
}
 
namespace FFT {
 
    const int K = 20, N = 1 << K, M = 32767;
 
    struct Complex {
        double real, imag;
        Complex(double real = 0, double imag = 0) : real(real), imag(imag) {}
    } a1[N], b1[N], a2[N], b2[N], c[N], w[N];
 
    inline Complex operator + (Complex a, Complex b) {
        return Complex(a.real + b.real, a.imag + b.imag);
    }
    inline Complex operator - (Complex a, Complex b) {
        return Complex(a.real - b.real, a.imag - b.imag);
    }
    inline Complex operator * (Complex a, Complex b) {
        return Complex(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real);
    }
 
    int rev[N];
 
    void Init(int k) {
        int n = 1 << k;
        for (int i = 1; i < n; ++i)
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
        for (int i = 0; i < n; ++i)
            w[i] = Complex(cos(M_PI * 2 / n * i), sin(M_PI * 2 / n * i));
        return;
    }
     
    void DFT(Complex *a, int k) {
        int n = 1 << k;
        for (int i = 0; i < n; ++i)
            if (i < rev[i]) swap(a[i], a[rev[i]]);
        for (int l = 2; l <= n; l <<= 1) {
            int m = l >> 1;
            for (Complex *p = a; p != a + n; p += l)
                for (int i = 0; i < m; ++i) {
                    Complex t = p[i + m] * w[n / l * i];
                    p[i + m] = p[i] - t;
                    p[i] = p[i] + t;
                }
        }
        return;
    }
 
    void IDFT(Complex *a, int k) {
        DFT(a, k);
        int n = 1 << k;
        reverse(a + 1, a + n);
        for (int i = 0; i < n; ++i) {
            a[i].real /= n;
            a[i].imag /= n;
        }
        return;
    }
 
    vector<int> FFT(vector<int> _a, int _n, vector<int> _b, int _m) {
        int n, k = 0;
        for (; (1 << k) < _n + _m + 1; ++k);
        n = 1 << k;
        Init(k);
        memset(a1, 0, sizeof(Complex) * n);
        memset(a2, 0, sizeof(Complex) * n);
        memset(b1, 0, sizeof(Complex) * n);
        memset(b2, 0, sizeof(Complex) * n);
        for (int i = 0; i <= _n; ++i) {
            a1[i].real = _a[i] >> 15;
            b1[i].real = _a[i] & M;
        }
        for (int i = 0; i <= _m; ++i) {
            a2[i].real = _b[i] >> 15;
            b2[i].real = _b[i] & M;
        }
        DFT(a1, k);
        DFT(b1, k);
        DFT(a2, k);
        DFT(b2, k);
        for (int i = 0; i < n; ++i)
            c[i] = a1[i] * a2[i];
        IDFT(c, k);
        vector<int> _c(_n + _m + 1);
        for (int i = 0; i <= _n + _m; ++i)
            _c[i] = Add(_c[i], Mul(llround(c[i].real) % MOD, 1 << 30));
        // _c[i] = (_c[i] + llround(c[i].real) % MOD * (1 << 30)) % MOD;
        for (int i = 0; i < n; ++i)
            c[i] = b1[i] * b2[i];
        IDFT(c, k);
        for (int i = 0; i <= _n + _m; ++i)
            _c[i] = Add(_c[i], llround(c[i].real) % MOD);
        // _c[i] = (_c[i] + llround(c[i].real)) % MOD;
        for (int i = 0; i < n; ++i)
            c[i] = a1[i] * b2[i] + b1[i] * a2[i];
        IDFT(c, k);
        for (int i = 0; i <= _n + _m; ++i)
            _c[i] = Add(_c[i], Mul(llround(c[i].real) % MOD, 1 << 15));
        // _c[i] = (_c[i] + llround(c[i].real) % MOD * (1 << 15)) % MOD;
        return _c;
    }
     
}
 
int main() {
    return 0;
}



模板3(LL版)

```cpp #include

using namespace std;

namespace Polynomial {

typedef long long LL;

const int K = 21, N = 1 << K;
const LL MOD = 998244353;

LL Pow(LL a, LL b) {
    LL c = 1;
    for (; b; a = a * a % MOD, b >>= 1)
        if (b & 1) c = c * a % MOD;
    return c;
}

LL inv[N];

void InitInv() {
    inv[1] = 1;
    for (int i = 2; i < N; ++i)
        inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
    return;
}

void Init(int k, int *sp, LL *w) {
    int n = 1 << k;
    w[0] = 1;
    w[1] = Pow(3, (MOD - 1) / n);
    for (int i = 2; i < n; ++i)
        w[i] = w[i - 1] * w[1] % MOD;
    sp[0] = 0;
    for (int i = 1; i < n; ++i)
        sp[i] = (sp[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
    return;
}

void DFT(vector<LL> &a, int k) {
    static int _k = 0;
    static int _sp[N * 2], *sp[K];
    static LL _w[N * 2], *w[K];
    for (; _k < k; ) {
        ++_k;
        sp[_k] = _sp + (1 << _k) - 1;
        w[_k] = _w + (1 << _k) - 1;
        Init(_k, sp[_k], w[_k]);
    }
    int n = 1 << k;
    for (int i = 0; i < n; ++i)
        if (i < sp[k][i]) swap(a[i], a[sp[k][i]]);
    for (int j = 1; j <= k; ++j) {
        int l = 1 << j, m = l >> 1;
        for (vector<LL> :: iterator p = a.begin(); p != a.end(); p += l)
            for (int i = 0; i < m; ++i) {
                LL t = p[i + m] * w[j][i] % MOD;
                if ((p[i + m] = p[i] - t) < 0) p[i + m] += MOD;
                if ((p[i] += t) >= MOD) p[i] -= MOD;
            }
    }
    return;
}

void IDFT(vector<LL> &a, int k) {
    DFT(a, k);
    int n = 1 << k, inv = Pow(n, MOD - 2);
    reverse(a.begin() + 1, a.end());
    for (int i = 0; i < n; ++i)
        (a[i] *= inv) %= MOD;
    return;
}

vector<LL> Multiply(vector<LL> a, vector<LL> b) {
    int _n = a.size(), _m = b.size(), k, n;
    for (k = 1; (1 << k) < (_n + _m - 1); ++k);
    n = 1 << k;
    a.resize(n);
    b.resize(n);
    DFT(a, k);
    DFT(b, k);
    for (int i = 0; i < n; ++i)
        (a[i] *= b[i]) %= MOD;
    IDFT(a, k);
    a.resize(_n + _m - 1);
    return a;
}
vector<LL> Multiply(vector<LL> a, vector<LL> b, int m) {
    if ((int)a.size() > m) a.resize(m);
    if ((int)b.size() > m) b.resize(m);
    int _n = a.size(), _m = b.size(), k, n;
    for (k = 1; (1 << k) < (_n + _m - 1); ++k);
    n = 1 << k;
    a.resize(n);
    b.resize(n);
    DFT(a, k);
    DFT(b, k);
    for (int i = 0; i < n; ++i)
        (a[i] *= b[i]) %= MOD;
    IDFT(a, k);
    a.resize(m);
    return a;
}
vector<LL>* _Multiply(vector<LL> &a, vector<LL> b) {
    int _n = a.size(), _m = b.size(), k, n;
    for (k = 1; (1 << k) < (_n + _m - 1); ++k);
    n = 1 << k;
    a.resize(n);
    b.resize(n);
    DFT(a, k);
    DFT(b, k);
    for (int i = 0; i < n; ++i)
        (a[i] *= b[i]) %= MOD;
    IDFT(a, k);
    a.resize(_n + _m - 1);
    return &a;
}
vector<LL>* _Multiply(vector<LL> &a, vector<LL> b, int m) {
    if ((int)b.size() > m) b.resize(m);
    int _n = a.size(), _m = b.size(), k, n;
    for (k = 1; (1 << k) < (_n + _m - 1); ++k);
    n = 1 << k;
    a.resize(n);
    b.resize(n);
    DFT(a, k);
    DFT(b, k);
    for (int i = 0; i < n; ++i)
        (a[i] *= b[i]) %= MOD;
    IDFT(a, k);
    a.resize(m);
    return &a;
}

vector<LL> Multiply(vector<LL> a, LL b) {
    b %= MOD;
    int n = a.size();
    for (int i = 0; i < n; ++i)
        a[i] = a[i] * b % MOD;
    return a;
}
vector<LL>* _Multiply(vector<LL> &a, LL b) {
    b %= MOD;
    int n = a.size();
    for (int i = 0; i < n; ++i)
        a[i] = a[i] * b % MOD;
    return &a;
}
 
vector<LL> Resize(vector<LL> a, int n) {
    return a.resize(n), a;
}
vector<LL>* _Resize(vector<LL> &a, int n) {
    a.resize(n);
    return &a;
}
 
vector<LL> Reciprocal(const vector<LL> &a) {
    int _n = a.size();
    if (!a[0]) {
        cerr << "irreversible" << endl;
        throw;
    }
    vector<LL> b(1, Pow(a[0], MOD - 2)), c;
    for (int n = 1, k = 0; n < _n; ) {
        n <<= 1;
        ++k;
        b.resize(n * 2);
        c.resize(n * 2);
        for (int i = 0; i < n; ++i)
            c[i] = (i < _n) ? a[i] : 0;
        DFT(b, k + 1);
        DFT(c, k + 1);
        for (int i = 0; i < n * 2; ++i)
            b[i] = b[i] * (MOD + 2 - b[i] * c[i] % MOD) % MOD;
        IDFT(b, k + 1);
        fill(b.begin() + n, b.end(), 0);
    }
    b.resize(_n);
    return b;
}

vector<LL> LeftShift(vector<LL> a, int n) {
    int _n = a.size();
    a.resize(_n + n);
    for (int i = _n + n - 1; i >= n; --i)
        a[i] = a[i - n];
    for (int i = 0; i < n; ++i)
        a[i] = 0;
    return a;
}
vector<LL>* _LeftShift(vector<LL> &a, int n) {
    int _n = a.size();
    a.resize(_n + n);
    for (int i = _n + n - 1; i >= n; --i)
        a[i] = a[i - n];
    for (int i = 0; i < n; ++i)
        a[i] = 0;
    return &a;
}
 
vector<LL> RightShift(vector<LL> a, int n) {
    int _n = a.size();
    for (int i = 0; i + n < _n; ++i)
        a[i] = a[i + n];
    if (_n - n > 0) a.resize(_n - n);
    else a = vector<LL>(1);
    return a;
}
vector<LL>* _RightShift(vector<LL> &a, int n) {
    int _n = a.size();
    for (int i = 0; i + n < _n; ++i)
        a[i] = a[i + n];
    if (_n - n > 0) a.resize(_n - n);
    else a = vector<LL>(1);
    return &a;
}
 
vector<LL> Add(vector<LL> a, const vector<LL> &b) {
    if (a.size() < b.size()) a.resize(b.size());
    for (int i = 0; i < (int)b.size(); ++i)
        if ((a[i] += b[i]) >= MOD) a[i] -= MOD;
    return a;
}
vector<LL>* _Add(vector<LL> &a, const vector<LL> &b) {
    if (a.size() < b.size()) a.resize(b.size());
    for (int i = 0; i < (int)b.size(); ++i)
        if ((a[i] += b[i]) >= MOD) a[i] -= MOD;
    return &a;
}

vector<LL> Add(vector<LL> a, LL b) {
    a[0] = (a[0] + b) % MOD;
    return a;
}
vector<LL>* _Add(vector<LL> &a, LL b) {
    a[0] = (a[0] + b) % MOD;
    return &a;
}
 
vector<LL> Subtract(vector<LL> a, const vector<LL> &b) {
    if (a.size() < b.size()) a.resize(b.size());
    for (int i = 0; i < (int)b.size(); ++i)
        if ((a[i] -= b[i]) < 0) a[i] += MOD;
    return a;
}
vector<LL>* _Subtract(vector<LL> &a, const vector<LL> &b) {
    if (a.size() < b.size()) a.resize(b.size());
    for (int i = 0; i < (int)b.size(); ++i)
        if ((a[i] -= b[i]) < 0) a[i] += MOD;
    return &a;
}
 
vector<LL> Subtract(vector<LL> a, LL b) {
    a[0] = (a[0] + MOD - b) % MOD;
    return a;
}
vector<LL>* _Subtract(vector<LL> &a, LL b) {
    a[0] = (a[0] + MOD - b) % MOD;
    return &a;
}
 
vector<LL> Divide(vector<LL> a, LL b) {
    LL inv = Pow(b % MOD, MOD - 2);
    int n = a.size();
    for (int i = 0; i < n; ++i)
        a[i] = a[i] * inv % MOD;
    return a;
}
vector<LL>* _Divide(vector<LL> &a, LL b) {
    LL inv = Pow(b % MOD, MOD - 2);
    int n = a.size();
    for (int i = 0; i < n; ++i)
        a[i] = a[i] * inv % MOD;
    return &a;
}
 
vector<LL> Divide(vector<LL> a, vector<LL> b) {
    int n = (int)a.size() - 1, m = (int)b.size() - 1;
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    a.resize(n - m + 1);
    b.resize(n - m + 1);
    a = Multiply(a, Reciprocal(b), n - m + 1);
    reverse(a.begin(), a.end());
    return a;
}
 
vector<LL> Modulo(const vector<LL> &a, const vector<LL> &b) {
    int m = (int)b.size() - 1;
    return Resize(Subtract(a, Multiply(Divide(a, b), b)), m);
}
 
vector<LL> Derivative(vector<LL> a) {
    int n = a.size();
    for (int i = 0; i + 1 < n; ++i)
        a[i] = a[i + 1] * (i + 1) % MOD;
    if (n > 1) a.resize(n - 1);
    return a;
}
vector<LL>* _Derivative(vector<LL> &a) {
    int n = a.size();
    for (int i = 0; i + 1 < n; ++i)
        a[i] = a[i + 1] * (i + 1) % MOD;
    if (n > 1) a.resize(n - 1);
    return &a;
}

vector<LL> Integral(vector<LL> a) {
    int n = a.size();
    a.resize(n + 1);
    for (int i = n; i; --i)
        a[i] = a[i - 1] * inv[i] % MOD;
    a[0] = 0;
    return a;
}
vector<LL>* _Integral(vector<LL> &a) {
    int n = a.size();
    a.resize(n + 1);
    for (int i = n; i; --i)
        a[i] = a[i - 1] * inv[i] % MOD;
    a[0] = 0;
    return &a;
}
 
vector<LL> Logarithm(vector<LL> a) {
    if (a[0] != 1) {
        cerr << "logarithm function undefined" << endl;
        throw;
    }
    int n = a.size();
    return Integral(Multiply(Derivative(a), Reciprocal(a), n - 1));
}
vector<LL>* _Logarithm(vector<LL> &a) {
    if (a[0] != 1) {
        cerr << "logarithm function undefined" << endl;
        throw;
    }
    int n = a.size();
    return _Integral(*_Multiply(*_Derivative(a), Reciprocal(a), n - 1));
}

vector<LL> Exponential(vector<LL> a) {
    if (a[0]) {
        cerr << "exponential function undefined" << endl;
        throw;
    }
    int _n = a.size();
    vector<LL> b(1, 1);
    for (int n = 1; n < _n; ) {
        n <<= 1;
        b.resize(n);
        _Multiply(b, Add(Subtract(vector<LL>(1, 1), Logarithm(b)), Resize(a, n)), n);
    }
    return *_Resize(b, _n);
}
 
vector<LL> Pow(vector<LL> a, LL b) {
    int n = a.size(), k;
    for (k = 0; k < n && !a[k]; ++k);
    LL c = a[k];
    _RightShift(a, k);
    _Divide(a, c);
    a.resize(n);
    a = Exponential(*_Multiply(*_Logarithm(a), b));
    _Multiply(a, Pow(c, b));
    if (k * b >= n) return vector<LL>(n, 0);
    return *_Resize(*_LeftShift(a, k * b), n);
}
     
struct Poly {
    vector<LL> c;
     
    Poly(vector<LL> c = vector<LL>(1)) : c(c) {}
     
    Poly(LL x) {
        c.resize(1);
        c[0] = x;
        return;
    }

    Poly* operator = (const LL x) {
        c.resize(1);
        c[0] = x;
        return this;
    }

    Poly Reciprocal() {
        return Poly(Polynomial::Reciprocal(c));
    }

    Poly Logarithm() {
        return Poly(Polynomial::Logarithm(c));
    }
     
    Poly* _Logarithm() {
        Polynomial::_Logarithm(c);
        return this;
    }

    Poly Exponential() {
        return Poly(Polynomial::Exponential(c));
    }

    Poly Pow(LL b) {
        return Poly(Polynomial::Pow(c, b));
    }

    Poly* Resize(int n) {
        c.resize(n);
        return this;
    }
     
    void _Resize(int n) {
        c.resize(n);
        return;
    }
     
    inline int Deg() const {
        return (int)c.size() - 1;
    }
     
    void Clear() {
        c = vector<LL>(1);
        return;
    }

    void Read(int n) {
        c.clear();
        c.resize(n + 1);
        for (int i = 0; i <= n; ++i) {
            scanf("%lld", &c[i]);
            c[i] %= MOD;
        }
        return;
    }

    void Print() {
        for (LL x : c)
            printf("%lld ", x);
        puts("");
        return;
    }
     
};

Poly Read(int n) {
    Poly a;
    a.Read(n);
    return a;
}
 
void _Read(int n, Poly &a) {
    a.Read(n);
    return;
}

void Print(Poly a) {
    a.Print();
    return;
}
 
void _Print(Poly &a) {
    a.Print();
    return;
}

Poly Resize(Poly a, int n) {
    return *a.Resize(n);
}

Poly* _Resize(Poly &a, int n) {
    a._Resize(n);
    return &a;
}

Poly Reciprocal(Poly &a) {
    return a.Reciprocal();
}

Poly Logarithm(Poly &a) {
    return a.Logarithm();
}

Poly* _Logarithm(Poly &a) {
    return a._Logarithm();
}

Poly Exponential(Poly &a) {
    return a.Exponential();
}

Poly Pow(Poly &a, LL b) {
    return a.Pow(b);
}

Poly operator << (const Poly &a, int n) {
    return Poly(LeftShift(a.c, n));
}

Poly* operator <<= (Poly &a, int n) {
    _LeftShift(a.c, n);
    return &a;
}
 
Poly operator >> (const Poly &a, int n) {
    return Poly(RightShift(a.c, n));
}

Poly* operator >>= (Poly &a, int n) {
    _RightShift(a.c, n);
    return &a;
}
 
Poly operator + (const Poly &a, const Poly &b) {
    return Poly(Add(a.c, b.c));
}

Poly operator + (const Poly &a, LL b) {
    return Poly(Add(a.c, b));
}
 
Poly* operator += (Poly &a, const Poly &b) {
    _Add(a.c, b.c);
    return &a;
}
 
Poly* operator += (Poly &a, LL b) {
    _Add(a.c, b);
    return &a;
}
 
Poly operator - (const Poly &a, const Poly &b) {
    return Poly(Subtract(a.c, b.c));
}
 
Poly operator - (const Poly &a, LL b) {
    return Poly(Subtract(a.c, b));
}
 
Poly* operator -= (Poly &a, const Poly &b) {
    _Subtract(a.c, b.c);
    return &a;
}
 
Poly* operator -= (Poly &a, LL b) {
    _Subtract(a.c, b);
    return &a;
}
 
Poly operator * (const Poly &a, const Poly &b) {
    return Poly(Multiply(a.c, b.c));
}
 
Poly operator * (const Poly &a, LL b) {
    return Poly(Multiply(a.c, b));
}
 
Poly* operator *= (Poly &a, LL b) {
    _Multiply(a.c, b);
    return &a;
}
 
Poly* operator *= (Poly &a, const Poly &b) {
    _Multiply(a.c, b.c);
    return &a;
}

Poly operator / (const Poly &a, const Poly &b) {
    return Poly(Divide(a.c, b.c));
}
 
Poly operator / (const Poly &a, LL b) {
    return Poly(Divide(a.c, b));
}
 
Poly* operator /= (Poly &a, const Poly &b) {
    a.c = Divide(a.c, b.c);
    return &a;
}
 
Poly* operator /= (Poly &a, LL b) {
    _Divide(a.c, b);
    return &a;
}
 
Poly operator % (const Poly &a, const Poly &b) {
    return Poly(Modulo(a.c, b.c));
}

Poly* operator %= (Poly &a, const Poly &b) {
    a.c = Modulo(a.c, b.c);
    return &a;
}

}

using namespace Polynomial;

Poly a, b;

int main() {
InitInv();
int n;
LL k;
scanf("%d%lld", &n, &k);
_Read(n - 1, a);
Print(Pow(a, k));
return 0;
}


<br><br>

<h3 id="4">模板4 多点求值 int版</h3>
[luogu5050 【模板】多项式多点求值](https://www.luogu.org/problemnew/show/P5050)
```cpp
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int MOD = 998244353;

inline int Add(int a, int b) {
    return (a + b >= MOD) ? (a + b - MOD) : (a + b);
}
inline int Sub(int a, int b) {
    return (a >= b) ? (a - b) : (a - b + MOD);
}
inline int Mul(int a, int b) {
    return (LL)a * b % MOD;
}
inline int Pow(int a, int b) {
    int c = 1;
    for (; b; a = Mul(a, a), b >>= 1)
        if (b & 1) c = Mul(c, a);
    return c;
}


namespace Poly {

    const int K = 22, N = 1 << K;

    // int inv[N];

    // void InitINV() {
    //     inv[1] = 1;
    //     for (int i = 2; i < N; ++i)
    //         inv[i] = Mul(Sub(0, MOD / i), inv[MOD % i]);
    //     return;
    // }
    
    void Init(int k, int *rev, int *w) {
        int n = 1 << k;
        rev[0] = 0;
        for (int i = 1; i < n; ++i)
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? (n >> 1) : 0);
        w[0] = 1;
        w[1] = Pow(3, (MOD - 1) / n);
        for (int i = 2; i < n; ++i)
            w[i] = Mul(w[i - 1], w[1]);
        return;
    }

    void DFT(vector<int> &a, int k) {
        static int _k = 0;
        static int _rev[N * 2], _w[N * 2];
        for (; _k <= k; ++_k)
            Init(_k, _rev + (1 << _k), _w + (1 << _k));
        int *rev = &_rev[1 << k];
        int n = 1 << k;
        for (int i = 0; i < n; ++i)
            if (i < rev[i]) swap(a[i], a[rev[i]]);
        for (int l = 1; l <= k; ++l) {
            int m = 1 << (l - 1);
            int *w = &_w[1 << l];
            for (vector<int> :: iterator p = a.begin(); p != a.begin() + n; p += 1 << l)
                for (int i = 0; i < m; ++i) {
                    int t = Mul(p[m + i], w[i]);
                    p[m + i] = Sub(p[i], t);
                    p[i] = Add(p[i], t);
                }
        }
        return;
    }

    void IDFT(vector<int> &a, int k) {
        DFT(a, k);
        int n = 1 << k;
        reverse(a.begin() + 1, a.begin() + n);
        int inv = Pow(n, MOD - 2);
        for (int i = 0; i < n; ++i)
            a[i] = Mul(a[i], inv);
        return;
    }

    vector<int> Multiply(vector<int> a, vector<int> b) {
        int _n = (int)a.size() - 1, _m = (int)b.size() - 1;
        int k = 0;
        for (; (1 << k) < _n + _m + 1; ++k);
        int n = 1 << k;
        a.resize(n);
        b.resize(n);
        DFT(a, k);
        DFT(b, k);
        for (int i = 0; i < n; ++i)
            a[i] = Mul(a[i], b[i]);
        IDFT(a, k);
        a.resize(_n + _m + 1);
        return a;
    }

    vector<int> Reciprocal(vector<int> a) {
        if (!a[0]) {
            cerr << "irreversible" << endl;
            throw;
        }
        int _n = (int)a.size();
        vector<int> b(1, Pow(a[0], MOD - 2)), c;
        for (int n = 1, k = 0; n < _n; ) {
            n <<= 1;
            ++k;
            b.resize(n << 1);
            c.resize(n << 1);
            for (int i = 0; i < n; ++i)
                c[i] = (i < _n) ? a[i] : 0;
            DFT(b, k + 1);
            DFT(c, k + 1);
            for (int i = 0; i < (n << 1); ++i)
                b[i] = Mul(b[i], Sub(2, Mul(b[i], c[i])));
            IDFT(b, k + 1);
            b.resize(n);
            // fill(b.begin() + n, b.end(), 0);
        }
        b.resize(_n);
        return b;
    }

    vector<int> Addition(vector<int> a, vector<int> b) {
        if (a.size() < b.size()) swap(a, b);
        int m = b.size();
        for (int i = 0; i < m; ++i)
            a[i] = Add(a[i], b[i]);
        return a;
    }

    vector<int> Subtract(vector<int> a, vector<int> b) {
        if (a.size() < b.size()) swap(a, b);
        int m = b.size();
        for (int i = 0; i < m; ++i)
            a[i] = Sub(a[i], b[i]);
        return a;
    }

    vector<int> Divide(vector<int> a, vector<int> b) {
        int n = (int)a.size() - 1, m = (int)b.size() - 1;
        if (n < m) return vector<int>(1);
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        a.resize(n - m + 1);
        b.resize(n - m + 1);
        a = Multiply(a, Reciprocal(b));
        a.resize(n - m + 1);
        reverse(a.begin(), a.end());
        return a;
    }

    vector<int> Module(vector<int> a, vector<int> b) {
        int n = (int)a.size() - 1, m = (int)b.size() - 1;
        if (n < m) return a;
        a = Subtract(a, Multiply(Divide(a, b), b));
        a.resize(m);
        return a;
    }
    
}

const int M = 64005;

int n, m;
vector<int> a;
int b[M];

int res[M];
vector<int> v[M * 4];

void Build(int k, int l, int r) {
    if (l == r) {
        v[k].push_back(Sub(0, b[l]));
        v[k].push_back(1);
        return;
    }
    int m = (l + r) / 2;
    Build(k << 1, l, m);
    Build(k << 1 | 1, m + 1, r);
    v[k] = Poly::Multiply(v[k << 1], v[k << 1 | 1]);
    return;
}

void Divide(int k, int l, int r, vector<int> a) {
    a = Poly::Module(a, v[k]);
    if (l == r) {
        res[l] = a[0];
        return;
    }
    int m = (l + r) / 2;
    Divide(k << 1, l, m, a);
    Divide(k << 1 | 1, m + 1, r, a);
    return;
}

int main() {
    scanf("%d%d", &n, &m);
    a.resize(n + 1);
    for (int i = 0; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= m; ++i)
        scanf("%d", &b[i]);
    Build(1, 1, m);
    Divide(1, 1, m, a);
    for (int i = 1; i <= m; ++i)
        printf("%d\n", res[i]);
    return 0;
}
posted @ 2019-02-25 21:42  tkandi  阅读(301)  评论(0编辑  收藏  举报