标签:
转自:http://blog.csdn.net/acdreamers/article/details/38929067 (ACdreamers)
分析:本题题意就是求自然数的幂和,但是它的case比较多。对于求幂和本身就需要的时间复杂度,如果继
续用上述方法来求自然数的幂和,5000个case会TLE,接下来介绍另一个求自然数幂和的方法,它是基于伯
努利数的,公式描述如下
可以看出只要我们预处理出每一项,就可以在线性时间内求得自然数的幂和。前面的倒数可以用递推法求逆元
预处理,组合数也可以预处理,也可以先预处理,现在关键是如何预处理伯努利数。
伯努利数满足条件,且有
那么继续得到
这就是伯努利数的递推式,逆元部分同样可以预处理。
另外,此题中我还学到了一种O(n)的递推法求前n个逆元的方法,详情见下篇转的博客。
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 5000) 第2 - T + 1行:每行2个数,N, K中间用空格分割。(1 <= N <= 10^18, 1 <= K <= 2000)
共T行,对应S(n) Mod 1000000007的结果。
3 5 3 4 2 4 1
225 30 10
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<iomanip> 6 using namespace std; 7 typedef long long LL; 8 const LL N = 2050; 9 const LL maxn = 2050; 10 const LL mod = 1000000007; 11 LL n, k; 12 13 LL comb[maxn][maxn], ber[maxn]; 14 15 void ex_gcd(LL a, LL b, LL& d, LL& x, LL &y){ 16 if(b==0){ 17 x = 1; y = 0; d = a; 18 return ; 19 } 20 ex_gcd(b, a%b, d, y, x); 21 y -= x*(a/b); 22 } 23 24 LL inv(LL a, LL p){ 25 LL x, y, d; 26 ex_gcd(a, p, d, x, y); 27 if(d==1) return (x%p + p)%p; 28 else return 0; 29 } 30 31 void init_comb(){ 32 comb[0][0] = 1; 33 for(int i = 1; i<maxn; ++i){ 34 comb[i][0] = comb[i][i] = 1; 35 for(int j = 1 ; j<i; ++j){ 36 comb[i][j] = (comb[i-1][j-1]%mod + comb[i-1][j]%mod)%mod; 37 } 38 } 39 } 40 //求伯努利数 41 void init_ber(){ 42 ber[0] = 1; 43 for(int i = 1 ; i<maxn; ++i){ 44 LL ans = 0; 45 for(int j = 0 ; j<i ; ++j) 46 ans = (ans + comb[i+1][j]*ber[j])%mod; 47 ans = -ans*inv(i+1, mod)%mod; 48 ber[i] = (ans%mod + mod)%mod; 49 } 50 } 51 52 //LL Inv[maxn]; 53 /*void bi(){ 54 Inv[1] = 1; 55 a for(int i=2; i<N; i++) 56 Inv[i] = (mod - mod / i) * Inv[mod % i] % mod; 57 //预处理伯努利数 58 for(int i= 1; i<100; ++i) cout<<Inv[i]<<" "; 59 cout<<endl; 60 for(int j= 1; j<100 ; ++j) cout<<inv(j,mod)<<" "; 61 }*/ 62 int main(){ 63 int T; 64 cin>>T; 65 init_comb(); 66 init_ber(); 67 while(T--){ 68 scanf("%lld %lld", &n, &k); 69 n %= mod; 70 LL ans = 0; 71 LL pow = (n+1)%mod; 72 for(int i = 1; i<=k+1 ; ++i){ 73 ans = (ans + comb[k+1][i]*ber[k+1-i]%mod*pow%mod)%mod; 74 pow = (pow*(n+1))%mod; 75 } 76 ans = ans*inv(k+1, mod)%mod; 77 ans = (ans%mod + mod)%mod; 78 printf("%lld\n", ans); 79 } 80 }
标签:
原文地址:http://www.cnblogs.com/topW2W/p/5413875.html