【CF622F】The Sum of the k-th Powers-拉格朗日插值
阿新 • • 發佈:2018-12-16
測試地址:The Sum of the k-th Powers 題目大意: 求對取模的值。 做法: 本題需要用到拉格朗日插值。 容易看出(或者用數學歸納法簡單證明),答案是一個關於的最高次為的多項式。問題是,怎麼得到這個多項式呢?這時候就要使用拉格朗日插值法。 拉格朗日插值法是一個可以由個二維平面上的點,構造出一個正好穿過這些點的次函式的演算法。有: 其中稱為插值基函式,其表示式為。 為什麼有這個式子呢?首先看存在性,注意到當且僅當時有取值,否則當時取值為,那麼顯然上面的函式可以穿過對應的點。至於唯一性好像要用一些玄學的東西證,你只需要知道個點一定能確定一個次函式就行了… 回到這一題,我們顯然可以用這些點來使用拉格朗日插值法,算出這些點顯然是的(或者你可以用線性篩優化到…)。接下來我們把代入上式: 後面的積式中,分子和分母可以分別預處理,分子只要處理出字首積和字尾積即可(不能用這個式子,因為有可能為),而對於分母,我們發現分母可以拆成兩個類似於下面這樣的部分:和,分別預處理出來即可,時間複雜度為(或者用線性求逆元優化成)。 所以我們就解決了此題,時間複雜度為(可以優化到)。 以下是本人程式碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll n,k,invp[1000010],invn[1000010],inv[1000010];
ll pre[1000010],suf[1000010];
ll power(ll a,ll b)
{
ll s=1,ss=a;
while(b)
{
if (b&1) s=s*ss%mod;
ss=ss*ss%mod;
b>>=1;
}
return s;
}
int main()
{
scanf("%lld%lld",&n,&k);
invp[0]=invn[0]=1;
pre[0]=n;
for(ll i=1;i<=k+1;i++)
{
invp[i]=invp[i-1]*power(i,mod-2)%mod;
invn[i]=invn[i-1]*power(mod-i,mod-2)%mod;
pre[i]=pre[i-1]*(n-i+mod)%mod;
}
suf[k+1]=(n-k-1+mod)%mod;
for(int i=k;i>=0;i--)
suf[i]=suf[i+1]*(n-i+mod)%mod;
ll ans=0,now=0;
for(int i=0;i<=k+1;i++)
{
if (k>0||i>0) now=(now+power(i,k))%mod;
ll tot=1;
if (i>0) tot=tot*pre[i-1]%mod;
if (i<k+1) tot=tot*suf[i+1]%mod;
ll nowtot=tot*invp[i]%mod*invn[k-i+1]%mod;
ans=(ans+now*nowtot)%mod;
}
printf("%lld",ans);
return 0;
}