多项式
文章目录
一 简介
**多项式的度:**对于一个多项式 f ( x ) f(x) f(x),称其最高次项的次数为该多项式的度,记作 d e g f deg\ f deg f。
多项式的乘法:
可以通过快速傅里叶变换在 O ( n l o g n ) O(nlogn) O(nlogn)下计算。
给定多项式 f ( x ) f(x) f(x)和 g ( x ) g(x) g(x):
f ( x ) = a 0 + a 1 x + ⋅ ⋅ ⋅ + a n x n g ( x ) = b 0 + b 1 x + ⋅ ⋅ ⋅ + b m x m f(x)=a_0+a_1x+···+a_nx^n \\ g(x)=b_0+b_1x+···+b_mx^m f(x)=a0+a1x+⋅⋅⋅+anxng(x)=b0+b1x+⋅⋅⋅+bmxm
计算多项式 Q ( x ) = f ( x ) ⋅ g ( x ) Q(x)=f(x)·g(x) Q(x)=f(x)⋅g(x):
Q ( x ) = ∑ i = 0 n ∑ j = 0 m a i b j x i + j = c 0 + c 1 x + ⋅ ⋅ ⋅ + c n + m x n + m Q(x)=\sum_{i=0}^{n}\sum_{j=0}^{m}a_ib_jx^{i+j}=c_0+c_1x+···+c_{n+m}x^{n+m} Q(x)=i=0∑nj=0∑maibjxi+j=c0+c1x+⋅⋅⋅+cn+mxn+m
多项式的逆元:
对于多项式 f ( x ) f(x) f(x),若存在 g ( x ) g(x) g(x)满足:
f ( x ) g ( x ) ≡ 1 ( m o d x n ) d e g g ≤ d e g f f(x)g(x)≡1\ (mod\ x^n) \\ deg\ g≤deg\ f f(x)g(x)≡1 (mod xn)deg g≤deg f
则称 g ( x ) g(x) g(x)为 f ( x ) f(x) f(x)在模 x n x^n xn意义下的逆元,记作 f − 1 ( x ) f^{-1}(x) f−1(x)。
多项式的余数和商:
对于多项式 f ( x ) , g ( x ) f(x),g(x) f(x),g(x),存在唯一的 Q ( x ) , R ( x ) Q(x),R(x) Q(x),R(x)满足:
f ( x ) = Q ( x ) g ( x ) + R ( x ) d e g Q = d e g f − d e g g d e g R < d e g g f(x)=Q(x)g(x)+R(x) \\ deg\ Q=deg\ f-deg\ g \\ deg\ R<deg\ g f(x)=Q(x)g(x)+R(x)deg Q=deg f−deg gdeg R<deg g
称 Q ( x ) Q(x) Q(x)为 g ( x ) g(x) g(x)除 f ( x ) f(x) f(x)的商, R ( x ) R(x) R(x)为 g ( x ) g(x) g(x)除 f ( x ) f(x) f(x)的余数,可记作:
f ( x ) = R ( x ) ( m o d g ( x ) ) f(x)=R(x)\ (mod\ g(x)) f(x)=R(x) (mod g(x))
多项式的对数函数与指数函数:
对于一个多项式 f ( x ) f(x) f(x),可以将其对数函数看作其与麦克劳林级数的复合:
l n ( 1 − f ( x ) ) = − ∑ i = 1 + ∞ f i ( x ) i l n ( 1 + f ( x ) ) = ∑ i = 1 + ∞ ( − 1 ) i − 1 f i ( x ) i ln(1-f(x))=-\sum_{i=1}^{+∞}\frac{f^i(x)}{i} \\ ln(1+f(x))=\sum_{i=1}^{+∞}\frac{(-1)^{i-1}f^i(x)}{i} ln(1−f(x))=−i=1∑+∞ifi(x)ln(1+f(x))=i=1∑+∞i(−1)i−1fi(x)
其指数函数可以定义:
e x p f ( x ) = e f ( x ) = ∑ i = 0 + ∞ f i ( x ) i ! exp\ f(x)=e^{f(x)}=\sum_{i=0}^{+∞}\frac{f^i(x)}{i!} exp f(x)=ef(x)=i=0∑+∞i!fi(x)
多项式的多点求值和插值:
多项式的多点求值:给出一个多项式 f ( x ) f(x) f(x)和 n n n个点 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn,求 f ( x 1 ) , f ( x 2 ) , . . . , f ( x n ) f(x_1),f(x_2),...,f(x_n) f(x1),f(x2),...,f(xn)。
多项式的插值:给出 n + 1 n+1 n+1个点 ( x 0 , y 0 ) , ( x 1 , y 1 ) , . . . , ( x n , y n ) (x_0,y_0),(x_1,y_1),...,(x_n,y_n) (x0,y0),(x1,y1),...,(xn,yn),求一个 n n n次多项式 f ( x ) f(x) f(x)使得这 n + 1 n+1 n+1个点都在 f ( x ) f(x) f(x)上。
两种操作实质是将多项式在系数表示和点值表示间转化。
二 拉格朗日插值
2.1 知识点
时间复杂度: O ( n 2 ) O(n^2) O(n2)
**问题:**给出 n n n个点 P i ( x i , y i ) P_i(x_i,y_i) Pi(xi,yi),将过这 n n n个点的最多 n − 1 n-1 n−1次的多项式记为 f ( x ) f(x) f(x),求 f ( k ) f(k) f(k)的值。
**差分法:**适用于 x i = i x_i=i xi=i的情况。
利用差分法求多项式 f ( x ) = ∑ i = 0 n a i x i f(x)=\sum_{i=0}^{n}a_ix^i f(x)=∑i=0naixi的多项式形式,时间复杂度 O ( n 2 ) O(n^2) O(n2)。
已知 f ( 1 ) f(1) f(1)至 f ( 6 ) f(6) f(6)的值分别为 1 , 5 , 14 , 30 , 55 , 91 1,5,14,30,55,91 1,5,14,30,55,91
KaTeX parse error: Undefined control sequence: \ at position 140: …\ \ 2\ \ \ \ \ \̲ ̲
第一行为 f ( x ) f(x) f(x)的连续的前 n n n项,之后每一行为上一行相邻两项的差值,最终会变成定值行,即可求解。
待定系数法:
设 f ( x ) = ∑ i = 0 n − 1 a i x i f(x)=\sum_{i=0}^{n-1}a_ix^i f(x)=∑i=0n−1aixi,将每个 x i x_i xi代入 f ( x ) f(x) f(x),得到一个由 n n n条 n n n元一次方程所组成的方程组,然后使用高斯消元求解
拉格朗日插值法:
有:
f ( x ) ≡ f ( a ) ( m o d ( x − a ) ) f(x)≡f(a)\ (mod\ (x-a)) f(x)≡f(a) (mod (x−a))
因为 f ( x ) − f ( a ) = ( a 0 − a 0 ) + a 1 ( x 1 − a 1 ) + a 2 ( x 2 − a 2 ) + ⋅ ⋅ ⋅ + a n ( x n − a n ) f(x)-f(a)=(a_0-a_0)+a_1(x^1-a^1)+a_2(x^2-a^2)+···+a_n(x^n-a^n) f(x)−f(a)=(a0−a0)+a1(x1−a1)+a2(x2−a2)+⋅⋅⋅+an(xn−an)有因子 ( x − a ) (x-a) (x−a)。
列出多项式线性同余方程组:
$$
\begin{cases} f(x)≡y_1\ (mod\ (x-x_1)) \ f(x)≡y_2\ (mod\ (x-x_2)) \ ··· \ f(x)≡y_n\ (mod\ (x-x_n)) \end{cases}
根 据 中 国 剩 余 定 理 : 根据中国剩余定理: 根据中国剩余定理:
M=\prod_{i=1}^{n}(x-x_i) \
m_i=\frac{M}{x-x_i}=\prod_{j≠i}(x-x_j)
KaTeX parse error: Can't use function '$' in math mode at position 2: $̲m_i$模$(x-x_i)$意…
m_i^{-1}=\prod_{j≠i}\frac{1}{x_i-x_j}
所 以 : 所以: 所以:
f(x)=\sum_{i=1}{n}y_im_im_i{-1}≡\sum_{i=1}^ny_i\prod_{j≠i}\frac{x-x_i}{x_i-x_j}\ (mod\ M)
$$
如果给定的点为连续的点,那么可以使用前缀后缀优化。
例如给定 ( 0 , f 0 ) , ( 1 , f 1 ) , ( 2 , f 2 ) , . . . , ( n , f n ) (0, f_0), (1, f_1), (2, f_2), ..., (n, f_n) (0,f0),(1,f1),(2,f2),...,(n,fn)
则记: p r e [ i ] = ∏ j = 0 i ( k − j ) , s u f f [ i ] = ∏ j = i n ( k − j ) , f a c t [ i ] = i ! pre[i] = \prod_{j=0}^{i}(k - j), suff[i] = \prod_{j=i}^{n}(k-j), fact[i] = i! pre[i]=∏j=0i(k−j),suff[i]=∏j=in(k−j),fact[i]=i!
则$ f(k)=\sum_{i=0}^{n} y_i\frac{pre[i-1]*suff[i+1]}{fact[i]*fact[n-i]} , 但 是 分 母 , 但是分母 ,但是分母fact[n-i]$可能出现负数,需要去判断,当 n − i n-i n−i 为奇数时,分母应该取负号。这样就可以预处理得到 f a c t fact fact数组,然后根据输入的k来 O ( n ) O(n) O(n)计算得到 p r e 、 s u f f pre、suff pre、suff数组,从而 O ( n ) O(n) O(n)完成 f ( k ) f(k) f(k)计算。
2.2 模板
2.1 随机给定n个点插值: O ( n 2 l o g n ) O(n^2log_n) O(n2logn)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 2010;
int mod = 998244353;
int n, k, x[MAXN], y[MAXN], res, s1, s2;
int qmi(int a, int k, int p) {
int res = 1 % p; // res记录答案, 模上p是为了防止k为0,p为1的特殊情况
while(k) {
// 只要还有剩下位数
if (k & 1) res = res * a % p; // 判断最后一位是否为1,如果为1就乘上a,模上p, 乘法时可能爆int,所以变成long long
k >>= 1; // 右移一位
a = a * a % p; // 当前a等于上一次的a平方,取模,平方时可能爆int,所以变成long long
}
return res;
}
int get_inv(int a, int p) {
return a % p == 0? -1: qmi(a, p - 2, p);
}
// n个点(x[i], y[i]),求f(k)
int Lagrange(int x[], int y[], int n, int k) {
int res = 0;
for (int i = 1; i <= n; i++) {
s1 = y[i] % mod; // s1计算分子
s2 = 1; // s2计算分母
for (int j = 1; j <= n; j++)
if (i != j)
s1 = s1 * (k - x[j]) % mod, s2 = s2 * (x[i] - x[j]) % mod; // 分别计算分子和分母
res += s1 * get_inv(s2, mod) % mod;
}
return (res % mod + mod) % mod;
}
signed main() {
scanf("%lld%lld", &n, &k);
for (int i = 1; i <= n; i++) scanf("%lld%lld", x + i, y + i); // 读入n个点
cout << Lagrange(x, y, n, k);
return 0;
}
2.2 给定连续n个点插值: O ( n ) O(n) O(n)
void init(int n, int mod) {
// 预处理逆元
LL res = 1;
for (int i = 1; i <= n + 2; ++i) res = res * i % mod; // 计算阶乘
fact[n + 2] = qmi(res, mod - 2, mod);
for (int i = n + 1; i >= 0; --i) fact[i] = (i + 1) * fact[i + 1] % mod; // 计算逆元
}
//给定最高次为n的多项式的n+1个点分别为:(0,f0),(1,f1),(2,f2)...(n,fn),求f(k)的值
LL Lagrange(LL f[], int n, int k) {
if (k <= n) return f[k];
pre[0] = suff[n + 1] = 1;
for (int i = 0; i <= n; ++i) pre[i + 1] = pre[i] * (k - i) % mod;
for (int i = n; i >= 0; --i) suff[i] = suff[i + 1] * (k - i) % mod;
LL fk = 0;
for (int i = 0; i <= n; ++i) {
LL tmp = f[i] * pre[i] % mod * suff[i + 1] % mod * fact[i] % mod * fact[n - i] % mod; // 计算 (pre[i-1]*suff[i+1]) / (fact[i]*fact[n-i])
if ((n - i) & 1) // 当 n-i 为奇数时,分母应该取负号。
fk = (fk - tmp + mod) % mod;
else
fk = (fk + tmp) % mod;
}
return fk;
}
int main() {
...
init(MAXN - 10, mod); // 预处理逆元
for (int i = 0; i <= n; ++i) cin >> f[i]; // 读入n+1个点
f[n + 1] = Lagrange(f, n, n + 1); // 得到f[n+1]
...
}
2.3 例题
P4781 【模板】拉格朗日插值
**题意:**给定 n n n个点 ( x i , y i ) (x_i,y_i) (xi,yi)确定唯一的多项式,并求出 f ( k ) m o d 998244353 f(k)\ mod\ 998244353 f(k) mod 998244353。
数据: 1 ≤ n ≤ 2 × 1 0 3 1≤n≤2×10^3 1≤n≤2×103, 1 ≤ x i , y i , k < 998244353 1≤x_i,y_i,k<998244353 1≤xi,yi,