模板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 #includeusing 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
", res[i]);
return 0;
}