【拉格朗日插值法】
阿新 • • 發佈:2019-02-02
對某個多項式函式,已知有給定的k + 1個取值點:
其中對應著自變數的位置,而對應著函式在這個位置的取值。
假設任意兩個不同的都互不相同,那麼應用拉格朗日插值公式所得到的拉格朗日插值多項式為:
其中每個為拉格朗日基本多項式(或稱插值基函式),其表示式為:
拉格朗日基本多項式的特點是在上取值為1,在其它的點上取值為0。
程式碼
//1.先呼叫 init(n)初始化 逆元陣列。
//2.估計出答案的最高次數,然後構造一個比最高次數多一項的插基陣列。
//3.然後呼叫polyval求第n項。
typedef long long LL;
const int MOD=1e9+7;
const int N=1020;
LL pod(LL x ,LL n)
{
LL ret=1;
while(n)
{
if(n&1)ret=ret*x%MOD;
n>>=1;
x=x*x%MOD;
}
return ret;
}
namespace Polyval
{
LL fac[N],invv[N],p1[N],p2[N];
void init(int n)
{
fac[0]=fac[1]=invv[0]=invv[1]=1;
for(int i=2; i<=n; i++)
fac[i]=fac[i-1]*i %MOD;
invv[n]=pod(fac[n],MOD-2);
for(int i=n; i>1; i--)
invv[i-1]=invv[i]*i%MOD;
}
LL polyval(int d,LL *a,LL n)
{
if(n<=d)return a[n];
p1[0]=1;
p2[d]=1;
for(LL i=0; i<=d; i++)
p1[i+1]=p1[i]*(n-i)%MOD;
for(LL i=d; i>0; i--)
p2[i-1]=p2[i]*(n-i)%MOD;
LL ans=0;
for(int i=0; i<=d; i++)
{
LL tem=a[i]*p1[i]%MOD*p2[i]%MOD*invv[i]%MOD*invv[d-i]%MOD;
cout<<tem<<endl;
if((d-i)&1)ans=(ans-tem+MOD)%MOD;
else ans=(ans+tem)%MOD;
}
ans=(ans+MOD)%MOD;
return ans;
}
}
LL b[N],a[N];
//求k次方的前n項和
int main()
{
int n,k;
Polyval::init(1010);
while(scanf("%d%d",&n,&k)!=EOF)
{
b[0]=0;
for(LL i=1;i<=k+1;i++) //和最高為k+1項
{
b[i]=(pod(i,k)+b[i-1])%MOD; //構造和的k+2個點
}
printf("%lld\n",Polyval::polyval(k+1,b,n));
}
}