求自然數冪和
阿新 • • 發佈:2018-08-09
art urn 得到 遞推法 targe ont 部分 分享圖片 spa
求自然數冪和,就是一條公式,然後用代碼實現;
公式描述如下:
可以看出只要我們預處理出每一項,就可以在線性時間內求得自然數的冪和。前面的倒數可以用遞推法求逆元
預處理,組合數也可以預處理,也可以先預處理,現在關鍵是如何預處理伯努利數。
伯努利數滿足條件,且有
那麽繼續得到
這就是伯努利數的遞推式,逆元部分同樣可以預處理。
代碼:
typedef long long ll;
typedef unsigned long long ull;
const ll N=2005;
const ll mod=1e9+7;
ll inv[N],B[N];
ll C[N][N];
ll tmp[N];
ll n,k;
void init()
{
//預處理組合數
for(int i=0;i<N;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j]%mod+C[i-1][j-1]%mod)%mod;
}
//預處理逆元
inv[1]=1;
for(int i=2;i<N;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
;
// 預處理伯努利數
B[0]=1;
for(int i=1;i<N;i++)
{
ll ans=0;
if(i==N-1)break;
for(int j=0;j<i;j++)
{
ans+=C[i+1][j]*B[j];
ans%=mod;
}
ans *=-inv[i+1];
ans=(ans%mod+mod)%mod;
B[i]=ans;
}
}
ll work(ll k)
{
ll ans=inv[k+1];
ll sum=0;
for(int i=1;i<=k+1;i++)
{
sum+=C[k+1][i]*tmp[i]%mod*B[k+1-i]%mod;
sum%=mod;
}
ans*=sum;
ans%=mod;
return ans;
}
ll sum(ll n,ll k)
{
if(n<0)return 0;
n%=mod;
tmp[0]=1;
for(int i=1;i<N;i++)
tmp[i]=tmp[i-1]*(n+1)%mod;
return work(k);
}
參考博客:https://blog.csdn.net/acdreamers/article/details/38929067
求自然數冪和