51nod 1228 序列求和 ( 1^k+2^k+3^k+...+n^k )

C为组合数,B为伯努利数

具体推到过程略

参考博客:http://blog.csdn.net/acdreamers/article/details/38929067#

(我的式子和博客中的不一样,不过思想是一样的)

 

具体见代码:

 1 const int MOD = 1000000000 + 7;
 2 
 3 
 4 const int maxn = 2000 + 10;
 5 LL C[maxn][maxn];
 6 LL inv[maxn];
 7 LL B[maxn];
 8 LL n, k;
 9 void init()
10 {
11     scanf("%lld%lld", &n, &k);
12 }
13 
14 void getC()
15 {    
16     C[0][0] = 1;
17     for(int i = 1; i < maxn; i++) {
18         C[i][0] = C[i][i] = 1;
19         for(int j = 1; j < i; j++)
20             C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
21     }
22 }
23 
24 void getInv() //O(n) 求所有逆元
25 {
26     inv[1] = 1;
27     for (int i = 2; i < maxn; i++)
28     {
29         inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
30     }
31 }
32 
33 void getB() //求伯努利数
34 {
35     B[0] = 1;
36     for (int i = 1; i < maxn - 1; i++)
37     {
38         for (int j = 0; j < i; j++)
39         {
40             B[i] = (B[i] + C[i+1][j] * B[j]) % MOD;
41         }
42         B[i] = (-inv[i+1] * B[i] % MOD + MOD) % MOD;
43     }
44 }
45 
46 LL ni[maxn];
47 void solve()
48 {
49     n %= MOD; //1e18会爆
50     ni[0] = 1;
51     for (int i = 1; i <= k + 1; i++) ni[i] = ni[i-1] * (n + 1) % MOD;
52     LL ans = 0;
53     for (int i = 0; i <= k; i++)
54     {
55         ans = (ans + C[k+1][i] * ni[k+1-i] % MOD * B[i] % MOD) % MOD;
56     }
57     ans = ans * inv[k+1] % MOD;
58     printf("%lld\n", ans);
59 }
60 
61 int main()
62 {
63     getInv();
64     getC();
65     getB();
66     int T;
67     scanf("%d", &T);
68     while (T--)
69     {
70         init();
71         solve();
72     }
73     return 0;
74 }

 

posted @ 2016-11-22 18:27  llysrv  阅读(394)  评论(0编辑  收藏  举报