51_1228 序列求和(伯努利数)(转)

转自:http://blog.csdn.net/acdreamers/article/details/38929067 (ACdreamers)

分析:本题题意就是求自然数的幂和,但是它的case比较多。对于求幂和本身就需要的时间复杂度,如果继

续用上述方法来求自然数的幂和,5000caseTLE,接下来介绍另一个求自然数幂和的方法,它是基于伯

努利数的,公式描述如下

可以看出只要我们预处理出每一项,就可以在线性时间内求得自然数的幂和。前面的倒数可以用递推法求逆元

预处理,组合数也可以预处理,也可以先预处理,现在关键是如何预处理伯努利数

   伯努利数满足条件,且有

那么继续得到

这就是伯努利数的递推式,逆元部分同样可以预处理。

    另外,此题中我还学到了一种O(n)的递推法求前n个逆元的方法,详情见下篇转的博客。

  1228 序列求和

题目来源: HackerRank

基准时间限制:3 秒 空间限制:131072 KB 分值: 160 难度:6级算法题

收藏

关注

T(n) = n^k,S(n) = T(1) + T(2) + ...... T(n)。给出n和k,求S(n)。

例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55。

由于结果很大,输出S(n) Mod 1000000007的结果即可。

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 5000)
第2 - T + 1行:每行2个数,N, K中间用空格分割。(1 <= N <= 10^18, 1 <= K <= 2000)

Output

共T行,对应S(n) Mod 1000000007的结果。

Input示例

3
5 3
4 2
4 1

Output示例

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     }

  

时间: 2024-12-10 23:22:26

51_1228 序列求和(伯努利数)(转)的相关文章

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

【蓝桥杯】 入门训练 序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 5050 数据规模与约定 1

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B

序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 锦囊1 锦囊2 锦囊3 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 505

蓝桥杯-入门训练 序列求和

入门训练 序列求和 时间限制:1.0s   内存限制:256.0MB 问题描述 求1+2+3+...+n的值. 输入格式 输入包括一个整数n. 输出格式 输出一行,包括一个整数,表示1+2+3+...+n的值. 样例输入 4 样例输出 10 样例输入 100 说明:有一些试题会给出多组样例输入输出以帮助你更好的做题. 一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低. 样例输出 5050 数据规模与约定 1

HDU 5358 First One 求和(序列求和,优化)

题意:给定一个含n个元素的序列,求下式子的结果.S(i,j)表示为seq[i...j]之和.注:对于log20可视为1.数据量n<=105. 思路:即使能够在O(1)的时间内求得任意S,也是需要O(n*n)来求和的. 对于这种题,一般就是研究式子,看有什么办法可以减少复杂度. 对于这个式子,S最大也不会超过longlong,确切计算,小于234.那么log的范围这么小,如果能够知道分别有多少个的话,那就快多了.可以看得出对于同一个i,log的结果是线性的,从1到34逐步递增的.那很好办,对于每个

51nod1229 序列求和 V2 【数学】

题目链接 B51nod1229 题解 我们要求 \[\sum\limits_{i = 1}^{n}i^{k}r^{i}\] 如果\(r = 1\),就是自然数幂求和,上伯努利数即可\(O(k^2)\) 否则,我们需要将式子进行变形 要与\(n\)无关 设 \[F(k) = \sum\limits_{i = 1}^{n} i^{k}r^{i}\] 自然数幂应该是不用去动了,两边乘个\(r\) \[rF(k) = \sum\limits_{i = 2}^{n + 1}r^{i}(i - 1)^{k}

动态规划_基础_任意子区间序列求和问题_滑动窗口解法_多种思路_分治思想演变

题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入描述 第一行是一个正整数 N ( 1 ≤ N ≤ 200000 ) ,表示了序列的长度. 接下来的 N 行包含 N 个绝对值不大于 10000 的整数 A [ i ] ,描述了这段序列. 输出描述 仅包括 1 个整数,为最大的子段和是多少,子段的最小长度为 1 . 样例输入 72-43-12-43 样例输出 4 Hint Origin: SidneyEdit by stdKonjac in 2020 解题思路: 关于求子区间求