日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

伯努利数与自然数幂和

發布時間:2024/4/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 伯努利数与自然数幂和 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天我們討論的問題是如何有效地求自然數的冪和。接下來以3個經典題目為例來講解。

?

題目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1864

?

分析:其實求自然數的冪和方法有很多種,先來看看普通的遞推求法,由于

?

????

?

???? 那么對于所有的累加得到

?

????

?

???? 進一步得到

?

????

?

???? 可以看出這是一個遞推式,如果我們記

?

??? ??

?

?????那么得到如下遞歸式

?

?????

?

?????遞歸出口是

?

?????

?

?????為了提高效率,在遞歸的時候需要記憶化。由于要用到大數,用Java實現。

?

代碼:

import java.math.*; import java.util.*;public class Main {public static final int N = 105;public static final BigInteger FLAG = (BigInteger.ZERO).subtract(BigInteger.ONE);public static BigInteger[][] C = new BigInteger[N][N];public static BigInteger[] ans = new BigInteger[N];public static void Init(){for(int i=0; i<N; i++){C[i][0] = C[i][i] = BigInteger.ONE;if(i == 0) continue;for(int j=1; j<i; j++)C[i][j] = C[i-1][j].add(C[i-1][j-1]);}}public static BigInteger Solve(BigInteger n, int k){if(ans[k].compareTo(FLAG) != 0){return ans[k];}if(k == 1){ans[k] = ((n.add(BigInteger.ONE)).multiply(n)).divide(BigInteger.valueOf(2));return ans[k];}BigInteger tmp = BigInteger.ONE;for(int i=0; i<k+1; i++){tmp = tmp.multiply(n.add(BigInteger.ONE));}tmp = tmp.subtract(n.add(BigInteger.ONE));BigInteger sum = BigInteger.ZERO;for(int i=1; i<k; i++){BigInteger t = C[k+1][i+1].multiply(Solve(n, k-i));sum = sum.add(t);}ans[k] = (tmp.subtract(sum)).divide(BigInteger.valueOf(k+1));return ans[k];}public static void main(String[] args){Init();Scanner cin = new Scanner(System.in);while(cin.hasNext()){BigInteger n = cin.nextBigInteger();int k = cin.nextInt();for(int i=0; i<N; i++){ans[i] = FLAG;}System.out.println(Solve(n, k));}} }


?

題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1228

?

分析:本題題意就是求自然數的冪和,但是它的case比較多。對于求冪和本身就需要的時間復雜度,如果繼

???? 續用上述方法來求自然數的冪和,5000caseTLE,接下來介紹另一個求自然數冪和的方法,它是基于伯

?????努利數的,公式描述如下

?

????

?

?????可以看出只要我們預處理出每一項,就可以在線性時間內求得自然數的冪和。前面的倒數可以用遞推法求逆元

???? 預處理,組合數也可以預處理,也可以先預處理,現在關鍵是如何預處理伯努利數

?

?????伯努利數滿足條件,且有

?

????

?

?????那么繼續得到

?

????

?

?????這就是伯努利數的遞推式,逆元部分同樣可以預處理。

?

代碼:

#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

?

?

總結

以上是生活随笔為你收集整理的伯努利数与自然数幂和的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。