多项式简介
我们讨论多项式时,基本是在模质数意义下的,最常见的是
一元多项式可以形象的理解为一个数组
它的“长度”
形式幂级数则拥有无限的长度
多项式可以看作其截取
我们经常在计算机中通过 vector<int>
或者数组表示。
cpp
constexpr int P = 998244353;
int mo(int u) {
return u >= P ? u - P : u;
}
struct Poly : public vector<int> {
#define T (*this)
using vector::vector;
int deg() {
return size();
}
Poly &redeg(int m) {
return resize(m), T;
}
Poly cut(int m) const {
return {begin(), begin() + min(m, deg())};
}
// 其他操作。。。
#undef T
};
constexpr int P = 998244353;
int mo(int u) {
return u >= P ? u - P : u;
}
struct Poly : public vector<int> {
#define T (*this)
using vector::vector;
int deg() {
return size();
}
Poly &redeg(int m) {
return resize(m), T;
}
Poly cut(int m) const {
return {begin(), begin() + min(m, deg())};
}
// 其他操作。。。
#undef T
};
加法
对于形式幂级数
cpp
friend Poly operator+(const Poly &f, const Poly &g) {
int m = max(f.deg(), g.deg());
Poly h = Poly(f).redeg(m);
for (int i = 0; i < g.deg(); i++)
h[i] = mo(h[i] + g[i]);
return h;
}
friend Poly operator-(const Poly &f, const Poly &g) {
int m = max(f.deg(), g.deg());
Poly h = Poly(f).redeg(m);
for (int i = 0; i < g.deg(); i++)
h[i] = mo(h[i] - g[i] + P);
return h;
}
friend Poly operator+(const Poly &f, const Poly &g) {
int m = max(f.deg(), g.deg());
Poly h = Poly(f).redeg(m);
for (int i = 0; i < g.deg(); i++)
h[i] = mo(h[i] + g[i]);
return h;
}
friend Poly operator-(const Poly &f, const Poly &g) {
int m = max(f.deg(), g.deg());
Poly h = Poly(f).redeg(m);
for (int i = 0; i < g.deg(); i++)
h[i] = mo(h[i] - g[i] + P);
return h;
}
乘法
形式幂级数的乘法也称为卷积,记作
这里给出一种
cpp
friend Poly operator*(const Poly &f, const Poly &g) {
int m = f.deg() + g.deg() - 1;
Poly h(m);
for (int i = 0; i < f.deg(); i++) {
for (int j = 0; j < g.deg(); j++) {
h[i + j] = (h[i + j] + 1ll * f[i] * g[j]) % P;
}
}
return h;
}
Poly operator*(int k) {
Poly f = T;
for (auto &fi : f)
fi = 1ll * fi * k % P;
return f;
}
friend Poly operator*(const Poly &f, const Poly &g) {
int m = f.deg() + g.deg() - 1;
Poly h(m);
for (int i = 0; i < f.deg(); i++) {
for (int j = 0; j < g.deg(); j++) {
h[i + j] = (h[i + j] + 1ll * f[i] * g[j]) % P;
}
}
return h;
}
Poly operator*(int k) {
Poly f = T;
for (auto &fi : f)
fi = 1ll * fi * k % P;
return f;
}
正常的实现是 FFT/NTT,其复杂度是
卷积本身也很重要,更深入的内容请看,详细请看 卷积
求导
形式幂级数
cpp
Poly deriv() const {
Poly f(deg() - 1);
for (int i = 1; i < deg(); i++)
f[i - 1] = 1ll * i * T[i] % P;
return f;
}
Poly deriv() const {
Poly f(deg() - 1);
for (int i = 1; i < deg(); i++)
f[i - 1] = 1ll * i * T[i] % P;
return f;
}
积分
形式幂级数
cpp
Poly integr() const {
Poly f(deg() + 1);
pre_inv(deg() + 1);
for (int i = deg(); i > 0; --i)
f[i] = 1ll * Inv[i] * T[i - 1] % P;
return f;
}
Poly integr() const {
Poly f(deg() + 1);
pre_inv(deg() + 1);
for (int i = deg(); i > 0; --i)
f[i] = 1ll * Inv[i] * T[i - 1] % P;
return f;
}
乘法逆
对于形式幂级数
那么称
容易证明,对于
指数
仿照分析学中指数函数的定义,我们可以定义形式幂级数的指数函数。
容易验证其仍有性质
对数
对数函数的定义是指数的逆函数,可以得出其展开式
容易验证其仍有性质