拉格朗日插值

So far 没啥好说的。终于有东西了。

原本的插值

给定 n 个坐标系上的点(x 坐标两两不同),让你求一个最高不超过 n1的多项式函数经过这些点。

n 个点的坐标为 (x1,y1),,(xn,yn),则函数

f(x)=i=1nyijixxjxixj

即为所求。

证明:

只要将 x=x1,x2,,xn 代入原式一切就明白了,每次代入都只有一项为 yi,其他为 0

xi 没有规律的话复杂度为 O(n2),也比高斯消元优秀。

P4781 【模板】拉格朗日插值

远古的提交

P5667 拉格朗日插值2

配合多项式。

提交

CF622F The Sum of the k-th Powers

i=1nikmod(109+7)

n 很大,要求 O(klogk)

不妨设答案为 Sk(n)

其实,Sk(n) 是关于 nk+1 次多项式,给出证明。

证明 1

做一下差分,发现 ΔSk(n)=nk,是一个 k 次多项式,而 k 次多项式的前缀和为 k+1 次多项式。

证明 2(仅供参考)

参考 我写的

Sk(n)=1k+1r=1k+1(k+1r)Bk+1r(n+1)r

其中 Bi 为伯努利数。


所以说我们任意找不同的 k+2 个点进行插值即可求出 Sk(n)

我们就选取好算的 1k+2 来插值,发现每个点的值和插值时的系数可以快速求出,就解决了。

点击查看代码
//https://www.luogu.com.cn/problem/CF622F
#include<bits/stdc++.h>
#define mod 1000000007
#define N 1000010
using namespace std;
int pl[N], pr[N], fac[N];
int qpow(int a, int b) {
int ans = 1;
for(; b >= 1; b >>= 1, a = 1ll * a * a % mod)
if(b & 1) ans = 1ll * ans * a % mod;
return ans;
}
signed main() {
int n, k, y = 0, ans = 0;
scanf("%d%d", &n, &k);
pl[0] = pr[k + 3] = fac[0] = 1;
for(int i = 1; i <= k + 2; i ++)
pl[i] = 1ll * pl[i - 1] * (n - i) % mod;
for(int i = k + 2; i >= 1; i --)
pr[i] = 1ll * pr[i + 1] * (n - i) % mod;
for(int i = 1; i <= k + 2; i ++)
fac[i] = 1ll * fac[i - 1] * i % mod;
for(int i = 1; i <= k + 2; i ++) {
y = (y + qpow(i, k)) % mod;
int a = pl[i - 1] * 1ll * pr[i + 1] % mod;
int b = fac[i - 1] * ((k - i) & 1 ? -1ll : 1ll) * fac[k + 2 - i] % mod;
ans = (ans + 1ll * y * a % mod * qpow(b, mod - 2) % mod) % mod;
}
printf("%d\n", (ans + mod) % mod);
return 0;
}

BZOJ3453. tyvj 1858 XLkxc

给定 k,a,n,d,p

f(x)=i=1xik

g(x)=i=1xf(i)

h(x)=i=0xg(a+id)

h(n)modp

1k123,0a,n,d123456789

p=1234567891 一个素数。

和上一道差不多,就是多套了几层,插值 k+4 个点即可。

时间 O(k3)

细节有一些。

点击查看代码
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
#define ll long long
const ll P=1234567891;//prime
const int N=130;
ll pw(ll x,ll y){
ll res=1;
while(y){
if(y&1){
(res*=x)%=P;
}
y>>=1;
(x*=x)%=P;
}
return res;
}
int k;
ll A,n,d,v[N],f[N],g[N],h[N];
ll calc(int lim,ll x){//[0,lim) 内整数已知点值,求 f(x)(x 对 P 取模)
ll ans=0,res;
For(i,0,lim-1){
res=1;
For(j,0,lim-1) if(i!=j) (res*=i-j+P)%=P;
res=pw(res,P-2)*v[i]%P;
For(j,0,lim-1) if(i!=j) (res*=x-j+P)%=P;
(ans+=res)%=P;
}
return ans;
}
void work(){
cin>>k>>A>>n>>d;
For(i,1,k+2) f[i]=(f[i-1]+pw(i,k))%P;
For(i,1,k+2) g[i]=(g[i-1]+f[i])%P;
copy(g,g+k+3,v);
h[0]=calc(k+3,A);
For(i,1,k+3) h[i]=(h[i-1]+calc(k+3,(A+i*d)%P))%P;
copy(h,h+k+4,v);
cout<<calc(k+4,n)<<"\n";
}
signed main(){ios::sync_with_stdio(false),cin.tie(nullptr);
int T;cin>>T;
while(T--)work();
return 0;}
//插值式子上面是 x-x_j 不是 x_i-x,公式记牢
//这里模数两倍爆 int!!

[AGC061F] Perfect Strings

看题解区吧,我也不是非常懂,属于拉插高端运用了。

posted @   ShaoJia  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示