最近多校碰到了有关拉格朗日插值法的题目,就系统学了下,具体解释在上一篇博客,下面给出模板。(以CF622F为例)
模板代码:
#pragma comment(linker, "/STACK:102400000,102400000")///手动扩栈
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define MOD 1000000007
#define PI acos(-1.0)
const int N = 1e6+10;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
ll n,k,ans,fac[N],y[N];
ll qp(ll a,ll b) {
ll s=1;
while(b) {
if(b&1) s=s*a%MOD;
a=a*a%MOD,b>>=1;
}
return s;
}
ll sv() {
fac[0]=fac[1]=1,y[1]=1;
for(int i=2;i<=k+2;i++) fac[i]=fac[i-1]*i%MOD;///预处理阶乘
for(int i=2;i<=k+2;i++) y[i]=(y[i-1]+qp(i,k))%MOD;///预处理求出每一项的结果
if(n<=k+2) return y[n];
ll sum=1,sig;
for (ll i=n-k-2;i<=n-1;i++) sum=sum*i%MOD;
for(ll i=1;i<=k+2;i++) {///k+1项的多项式有k+2项
ll fz=sum*qp(n-i,MOD-2)%MOD;///分子
ll fm=qp(fac[i-1]*fac[k+2-i]%MOD,MOD-2);///分母
if((k+2-i)%2==0) sig=1;///正负号
else sig=-1;
ans=(ans+MOD+sig*y[i]*fz%MOD*fm%MOD+MOD)%MOD;
}
return ans;
}
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>k;
cout<<sv()<<endl;
return 0;
}