Bernoulli Number
今天我們討論的問題是如何有效地求自然數的冪和。接下來以3個經典題目為例來講解。
?
題目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1864
?
分析:其實求自然數的冪和方法有很多種,先來看看普通的遞推求法,由于
?
?????
?
???? 那么對于所有的累加得到
?
?????
?
???? 進一步得到
?
?????
?
???? 可以看出這是一個遞推式,如果我們記
?
??? ??
?
?????那么得到如下遞歸式
?
??????
?
?????遞歸出口是
?
??????
題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1228
?
分析:本題題意就是求自然數的冪和,但是它的case比較多。對于求冪和本身就需要的時間復雜度,如果繼
???? 續用上述方法來求自然數的冪和,5000個case會TLE,接下來介紹另一個求自然數冪和的方法,它是基于伯
?????努利數的,公式描述如下
?
?????
?
?????可以看出只要我們預處理出每一項,就可以在線性時間內求得自然數的冪和。前面的倒數可以用遞推法求逆元
???? 預處理,組合數也可以預處理,也可以先預處理,現在關鍵是如何預處理伯努利數。
?
?????伯努利數滿足條件,且有
?
?????
?
?????那么繼續得到
?
?????
?
?????這就是伯努利數的遞推式,逆元部分同樣可以預處理。
?
代碼:
#include <iostream> #include <string.h> #include <stdio.h>using namespace std; typedef long long LL; const LL MOD = 1000000007; const int N = 2005;LL C[N][N]; LL B[N],Inv[N]; LL Tmp[N]; LL n;void Init() {//預處理組合數for(int i=0; i<N; i++){C[i][0] = C[i][i] = 1;if(i == 0) continue;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(int 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; }int main() {int T;Init();scanf("%d", &T);while(T--){int k;scanf("%I64d %d", &n, &k);n %= MOD;Tmp[0] = 1;for(int i=1; i<N; i++)Tmp[i] = Tmp[i-1] * (n + 1) % MOD;printf("%I64d\n", Work(k));}return 0; }題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1258
?
分析:本題與上題不同的是值比較大,達到50000,如果采用同樣的方法,會TLE的。那么必定要進行優化。
?
???? 參考Pick大神的方法,如下
?
????
?
???? 鏈接:http://picks.logdown.com/posts/189620-the-inverse-element-of-polynomial
?
總結
以上是生活随笔為你收集整理的Bernoulli Number的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 剪辑视频怎么添加背景视频
- 下一篇: ios开发工具_7个基本的ios开发人员