I will no longer be a|

yabnto

园龄:2年8个月粉丝:14关注:17

拉格朗日插值

CSR:又拉又插的东西(又垃圾,又傻叉)

JCY:什么你拉插了一晚上?(我学习拉插学了一晚上)JCY

什么是拉插

给定一些点值,是否可以求出一个函数,使得函数图像穿过这些点,并求出给定的 x 所对应的 y

初步思路

前置

我们想到两个点肯定可以确定一条直线,而三个点肯定可以确定一条抛物线,所以我们猜测 n+1 个点肯定可以确定一条 n 次的函数

正文:构造

考虑到我们可以强行让 x 取到某个值(比如 xi)时,它所对应的值为 yi 那么可以将式子变成 f(x)=yik 那么如何构造 k 便是我们要考虑的了,当 x 不取 xi、在取其它 xj 的时候,我们可以通过一个 xxj 来将其变为 0,可当 xi 时,会有一些其他的东西混进去 (xxj 带来的) 所以我们在构造一个 aiaj 就可以将前面带了的给去掉,考虑到上面是一个 0 就变成全 0 所以上面用乘法,所以将前面的去掉的部分我们也用乘法,两个部分一除,便是答案(哇,好抽象):

f(x)=yixxixixj

我们也可以将其理解为构造出来一个 k 来将函数扭成平滑曲线(可以从分段函数,到用平滑曲线来链接)

CF622F The Sum of the k-th Powers

首先我们要证明 ik 是个 k+1 次多项式,然后这里可以用 nk(n1)k 来证明差分后的次数会 1 然后我们便可以证明上述命题(说了跟说了似的,算了自行推导),然后我们便可以考虑拉插,考虑到这些 x 值连续,所以我们便可以通过一些奇怪的做法将整个优化到 O(n)(哇,我真是个天才,这个也还不如自行推导)

#include <iostream>
using namespace std;
using ll = long long;
const int MaxN = 1e6 + 10, mod = 1e9 + 7;
ll f[MaxN], pr[MaxN], pl[MaxN], y[MaxN], n, k, ans, sum = 1;
ll qpow(ll a, ll b) {
ll res = 1;
for (ll i = 1; i <= b; i <<= 1) {
(b & i) && (res = res * a % mod);
a = a * a % mod;
}
return res;
}
int main() {
cin >> n >> k, f[0] = pl[0] = pr[k + 3] = 1;
for (int i = 1; i <= k + 2; i++) {
f[i] = f[i - 1] * i % mod, sum = sum * (n - i) % mod;
pl[i] = pl[i - 1] * (n - i) % mod;
}
for (int i = k + 2; i >= 1; i--) {
pr[i] = pr[i + 1] * (n - i) % mod;
}
for (int i = 1; i <= k + 2; i++) {
y[i] = (y[i - 1] + qpow(i, k)) % mod;
}
for (int i = 1; i <= k + 2; i++) {
ll a = pl[i - 1] * pr[i + 1] % mod, b = f[i - 1] * f[k + 2 - i] % mod * ((k + 2 - i) % 2 ? -1 : 1) % mod;
ans = (ans + a * qpow(b, mod - 2) % mod * y[i] % mod) % mod;
}
cout << (ans % mod + mod) % mod << endl;
return 0;
}

P4463 [集训队互测 2012] calc

这个首先得出 dp 式子(什么,这个不知道你学拉插干什么?):

fi,j=fi1,j1j+fi,j1

gi=fn,i,然后同样用差分可以得到 fi,jfi,j1=gi1,然后看 dp 式子分析多项式次数:

gi1=gi1+1

那么我们可以得到 \(g_i = g_{i - 1) + 2\)

所以 gn=2n

所以我们便知道 fn,i 是一个 2n 次多项式,所以我们可以求出前面 2n+1 个点的点值,然后拉插启动!

#include <iostream>
using namespace std;
using ll = long long;
const int MaxN = 2e3 + 10;
ll f[MaxN][MaxN], a[MaxN], b[MaxN], n, k, p, mod, ans, sum = 1;
ll qpow(ll a, ll b) {
ll res = 1;
for (ll i = 1; i <= b; i <<= 1) {
(b & i) && (res = res * a % mod);
a = a * a % mod;
}
return res;
}
int main() {
cin >> k >> n >> p, mod = p;
for (int i = 0; i <= 2 * n + 1; i++) {
f[0][i] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 2 * n + 1; j++) {
f[i][j] = (f[i - 1][j - 1] * j % mod + f[i][j - 1]) % mod;
}
}
for (int i = 1; i <= 2 * n + 1; i++) {
a[i] = i;
}
for (int i = 1; i <= 2 * n + 1; i++) {
b[i] = f[n][i];
sum = 1;
for (int j = 1; j <= 2 * n + 1; j++) {
if (i != j) sum = ((sum * (k - a[j]) % mod) + mod) % mod, sum = sum * (qpow(((a[i] - a[j]) % mod + mod) % mod, mod - 2)) % mod;
}
ans = (ans + sum * b[i] % mod) % mod;
}
for (int i = 1; i <= n; i++) {
ans = ans * i % mod;
}
cout << ans << endl;
return 0;
}

本文作者:yabnto

本文链接:https://www.cnblogs.com/ybtarr/p/18401931

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yabnto  阅读(22)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 光辉岁月 Audio artist
  3. 3 名前を呼ぶよ Audio artist
  4. 4 战歌 Audio artist
  5. 5 時を越えた想い Audio artist
  6. 6 所念皆星河 Audio artist
  7. 7 See you again Audio artist
時を越えた想い - Audio artist
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

Not available

点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起