维基百科链接
L ( x ) = ∑ i = 0 k y i ∏ j = 0 , i ≠ j k x − x j x i − x j L(x)=\sum_{i=0}^{k}y_i\prod_{j=0,i\neq j}^{k} \frac{x-x_j}{x_i-x_j} L(x)=i=0∑kyij=0,i=j∏kxi−xjx−xj
l i ( x ) = ∏ j = 0 , i ≠ j k x − x j x i − x j l_i(x)=\prod_{j=0,i\neq j}^{k} \frac{x-x_j}{x_i-x_j} li(x)=j=0,i=j∏kxi−xjx−xj
其中 l i ( x i ) = 1 l_i(x_i)=1 li(xi)=1,其余的 x 0 x_0 x0 到 x k x_k xk 带入皆为0。这样才能使得 L ( x i ) = y i L(x_i)=y_i L(xi)=yi 成立
通常情况下,我们可以对 x i x_i xi 取连续的值。那么就可以改造一下,取 x 1 = 1 , x 2 = 2 , … , x k + 1 = k + 1 x_1=1,x_2=2,\dots,x_{k+1}=k+1 x1=1,x2=2,…,xk+1=k+1,这 k + 1 k+1 k+1 项来进行插值,可以得到
L ( x ) = ∑ i = 1 k + 1 y i ∏ j = 1 , i ≠ j k + 1 x − x j x i − x j = ∑ i = 1 k + 1 y i ∏ j = 1 , i ≠ j k + 1 x − j i − j = ∑ i = 1 k + 1 y i ( x − 1 ) ( x − 2 ) … ( x − ( j − 1 ) ) ( x − ( j + 1 ) ) … ( x − ( k + 1 ) ) ( i − 1 ) ! ( k + 1 − i ) ! ( − 1 ) k + 1 − i L(x)=\sum_{i=1}^{k+1}y_i\prod_{j=1,i\neq j}^{k+1} \frac{x-x_j}{x_i-x_j}\\ =\sum_{i=1}^{k+1}y_i\prod_{j=1,i\neq j}^{k+1} \frac{x-j}{i-j}\\ =\sum_{i=1}^{k+1}y_i \frac{ (x-1)(x-2)\dots(x-(j-1))(x-(j+1))\dots(x-(k+1))}{(i-1)!(k+1-i)!(-1)^{k+1-i}} L(x)=i=1∑k+1yij=1,i=j∏k+1xi−xjx−xj=i=1∑k+1yij=1,i=j∏k+1i−jx−j=i=1∑k+1yi(i−1)!(k+1−i)!(−1)k+1−i(x−1)(x−2)…(x−(j−1))(x−(j+1))…(x−(k+1))
对这个式子计算可以得到模板:
int pref[K+10],suff[K+10],dy[K+10];;
int Lagrange(int k,int dy[],ll x)
{
if(x<=k+1) return dy[x];
pref[0]=1;
for(int j=1; j<=k+1; ++j) pref[j]=1ll*pref[j-1]*(x-j)%mod;
suff[k+2]=1;
for(int j=k+1; j>=1; --j) suff[j]=1ll*suff[j+1]*(x-j)%mod;
ll ans=0;
for(int i=1; i<=k+1; ++i)
{
ll tmp=1ll*dy[i]*pref[i-1]%mod*suff[i+1]%mod*finv[i-1]%mod*finv[k+1-i]%mod;
if(k+1-i&1) ans=(ans-tmp+mod)%mod;
else ans=(ans+tmp)%mod;
}
return ans;
}
链接:https://codeforces.com/contest/622/problem/F
题意:给定 n、k,计算 ∑ i = 1 n i k ( 1 ≤ n ≤ 1 0 9 , 0 ≤ k ≤ 1 0 k ) \sum_{i=1}^ni^k\ (1\le n \le 10^9, 0\le k \le 10^k) ∑i=1nik (1≤n≤109,0≤k≤10k)
思路:带入 x = 1 x = 1 x=1 到 k + 1 k+1 k+1,这前 k + 1 k+1 k+1 项,进行插值找到第 n n n 项
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
ll qpow(ll base,ll n,ll mod)
{
ll ret=1;
while(n)
{
if(n&1)
ret=ret*base%mod;
base=base*base%mod;
n>>=1;
}
return ret;
}
const int K=1e6+10;
int fac[K+10],finv[K+10];
void init()
{
fac[0]=fac[1]=1;
for(int i=2; i<=K; ++i)
fac[i]=1ll*fac[i-1]*i%mod;
finv[K]=qpow(fac[K],mod-2,mod);
for(int i=K-1; i>=0; --i)
finv[i]=1ll*finv[i+1]*(i+1)%mod;
}
int pref[K+10],suff[K+10],dy[K+10];;
int Lagrange(int k,int dy[],ll x)
{
if(x<=k+1) return dy[x];
pref[0]=1;
for(int j=1; j<=k+1; ++j) pref[j]=1ll*pref[j-1]*(x-j)%mod;
suff[k+2]=1;
for(int j=k+1; j>=1; --j) suff[j]=1ll*suff[j+1]*(x-j)%mod;
ll ans=0;
for(int i=1; i<=k+1; ++i)
{
ll tmp=1ll*dy[i]*pref[i-1]%mod*suff[i+1]%mod*finv[i-1]%mod*finv[k+1-i]%mod;
if(k+1-i&1) ans=(ans-tmp+mod)%mod;
else ans=(ans+tmp)%mod;
}
return ans;
}
int n,k;
int main()
{
init();
scanf("%d%d",&n,&k);
for(int i=1; i<=k+2; ++i)
dy[i]=qpow(i,k,mod);
for(int i=1; i<=k+2; ++i)
dy[i]=(1ll*dy[i]+dy[i-1])%mod;
printf("%d\n",Lagrange(k+1,dy,n));
return 0;
}