拉格朗日插
拉格朗日插
拉格朗日插值:给定 \(n+1\) 个点 \((x_i,y_i)\),确定一个 \(n\) 次多项式 \(f\) 对其求值。
\[f(k)=\sum_{i=0}^{n}y_i \prod_{i\neq j}\frac{k-x_j}{x_i-x_j}
\]
正确性可以通过带入 \(x_i\) 验证,配合小学数学知识。
cin >> n >> k, --n;
up(i,0,n) cin >> x[i] >> y[i];
up(i,0,n) up(j,0,n) inv[i][j]=ksm(x[i]-x[j],P-2);
up(i,0,n) {
int mul=y[i];
up(j,0,n) if(i^j) mul=mul*(k-x[j])%P*inv[i][j]%P;
f=(f+mul)%P;
}
cout << (f%P+P)%P;
连续取值的拉格朗日插
连续取值的拉格朗日插:
\[f(k)=\sum_{i=0}^{n}y_i\prod_{i\neq j}\frac{k-j}{i-j}
\]
考虑处理 \(pre[i]=\prod_{j=0}^{i}k-j,suf[i]=\prod_{j=i}^n k-j,fac[i]=\prod_{j=0}^ii\),那么有如下柿子,注意 \(n-i\) 为奇数时应取负号 >w<
\[f(k)=\sum_{i=0}^n y_i\frac{pre[i-1]\times suf[i+1]}{fac[i-1]\times fac[n-i]}
\]
k 次幂和
观察可得 \(\sum_{i=1}^n i^k\) 是一个 \(k+1\) 次多项式可以带入 \(k+2\) 个值拉插求求,复杂度 \(O(n)\)。证明本来想要因为我又菜又笨又懒就算了,啊啊啊看官见笑了呜呜呜诶诶诶诶诶诶(
inv[0]=inv[1]=mul[0]=1;
up(i,2,2e6) inv[i]=inv[P%i]*(P-P/i)%P;
up(i,1,2e6) mul[i]=mul[i-1]*inv[i]%P;
cin >> n >> k, pre[0]=n, suf[k+1]=n-k-1;
up(i,1,k+1) pre[i]=pre[i-1]*(n-i)%P;
dn(i,k, 0) suf[i]=suf[i+1]*(n-i)%P;
up(i,0,k+1) {
y=(y+ksm(i,k))%P;
int qwq=((k+i)&1)?y:-y;
if(i>0) qwq=qwq*pre[i-1]%P*mul[i]%P;
if(i<k+1) qwq=qwq*suf[i+1]%P*mul[k+1-i]%P;
out=(out+qwq)%P;
}
cout << (out+P)%P;
重心拉格朗日插
\[f(k)=\sum_{i=0}^n y_i \prod_{i\neq j} (k-x_i) \prod_{i\neq j} \frac{1}{x_i-x_j}
\]
其实就是这样子求值快一点点。