本文最后更新于:2022年1月19日 晚上
中国剩余定理和Lagrange插值法
引言
很巧,高代课讲到了Lagrange插值法,凭着“上课听不明白只好下课自己搞”的意志,我学学证明顺带来写个板子。
前置知识:中国剩余定理(CRT)
中国剩余定理是用来求解形如
的线性同余方程组的解的。其中,,我们需要找出最小的非负整数解。
解法
设,,,其中。
故可以构造一个解
由此,可以求出任意解
**最小正整数解**即为
证明
显然,在第个同余方程里,
所以,满足题意。
乘法逆元
若,则称是在意义下的逆元。
用扩展欧几里得来求解
过程如下:
$$
因为ax+by=(a, b)\
且b*x’+(a%b)y’=(b,a%b)\
a%b=a-\lfloor\frac{a}{b}\rfloorb
$$
$$
有ay’+b(x’-\lfloor\frac{a}{b}\rfloory’)=(a,b)\
故x=y’,y=(x’-\lfloor\frac{a}{b}\rfloory’)
$$
显然,,故令,则,故,可得为在下的逆元,即为题设所求。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ll n, a[maxn], m[maxn], Mi[maxn], M = 1, X;
void exgcd(ll a, ll b, ll &x, ll &y) { if(b == 0) {x = 1; y = 0; return;} exgcd(b, a % b, x, y); ll z = x; x = y, y = z - y * (a / b); }
void CRT() { n = read(); rep(i, 1, n) { m[i] = read(), a[i] = read(); M *= m[i]; } rep(i, 1, n) { Mi[i] = M / m[i]; ll x = 0, y = 0; exgcd(Mi[i], m[i], x, y); X += a[i] * Mi[i] * (x < 0 ? (x + m[i]):x); } cout << X % M << endl; }
|
正片:Lagrange插值
多项式储备知识(多项式余数)
已知多项式
下证:
已知
可知,当时,该子项恒成立
故余数必为的项之和,即
模意义下的推导过程
由上述可以得到一个关于的同余方程组,即
根据中国剩余定理
得在意义下的逆元为
故有
又唯一,故
即为Lagrange插值的表达式
通常意义下的推导过程
已知过个点,以及其在轴上的投影
考虑构造个函数使得其过点,
$$
\left{
\right.
$$
则可知所需函数.
则可设,将代入可得,所以
由此导出Lagrange插值在通常意义下的公式,如下
与上述在模意义下的Lagrange插值公式相同
代码实现(对时,即需要求的值的代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const ll p = 998244353; ll n, y[maxn], x[maxn], k; ll ans, s1, s2;
ll fastmod(ll a, ll k) { ll base = 1; while(k) { if(k & 1) base = base * a % p; a = a * a % p; k >>= 1; } return base % p; }
ll inv(ll x) { return fastmod(x, p - 2); }
void Lagrange() { n = read(), k = read(); rep(i, 1, n) { x[i] = read(), y[i] = read(); } rep(i, 1, n) { s1 = y[i] % p; s2 = 1LL; rep(j, 1, n) { if(i != j) { s1 = s1 * (k - x[j]) % p; s2 = s2 * (x[i]-x[j]) % p; } } ans += s1 * inv(s2) % p; } printf("%lld\n", (ans % p + p) % p); }
|