1. 程式人生 > >求自然數冪和

求自然數冪和

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

求自然數冪和