[51nod1228]序列求和
2016-07-10 22:09
281 查看
题目大意
设T(n) = n^k,S(n) = ∑ni=1T(i)。给出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的结果即可。
数据范围
T≤5000k≤2000
N≤1018
分析
n很大,所以复杂度不应该带n关于求自然数幂和,这里用到了伯努利数。
设伯努利数第i项为B[i],那么∑i=1nik=1k+1∑i=1k+1Cik+1B[k+1−i](n+1)i
时间复杂度O(Tk)
伯努利数
伯努利数是18世纪瑞士数学家雅各布·伯努利引入的一个数。——百度百科
设伯努利数第n项为B
。B[n]=⎧⎩⎨1−1n+1∑n−1k=0Ckn+1B[k]n=0n≥1
伯努利数的性质:
当n≥1时,∑nk=0Ckn+1B[k]=0
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=2005,mo=1e9+7; typedef long long LL; int T,k,b[maxn],c[maxn][maxn],Inv[maxn],ans,tmp; LL n; int main() { c[0][0]=1; for (int i=1;i<maxn;i++) { for (int j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j]) % mo; c[i][0]=1; } Inv[1]=1; for (int i=2;i<maxn;i++) Inv[i]=(LL)Inv[mo % i] * (mo-mo/i) % mo; b[0]=1; for (int i=1;i<maxn;i++) { b[i]=0; for (int k=0;k<i;k++) b[i]=(b[i]+(LL)c[i+1][k]*b[k] % mo) % mo; b[i]=((LL)b[i]*(-Inv[i+1]) % mo+mo)%mo; } scanf("%d",&T); while (T--) { scanf("%lld %d",&n,&k); n++; n%=mo; tmp=n; ans=0; for (int i=1;i<=k+1;i++) { ans=(ans+(LL)c[k+1][i]*b[k+1-i]%mo*n%mo) % mo; n=(LL)n*tmp % mo; } ans=(LL)ans*Inv[k+1] % mo; printf("%d\n",ans); } return 0; }
相关文章推荐
- unity3d Vector3.Lerp解析
- GitHub 教程资源目录
- 4、接口与内部类
- Android实现无标题栏全屏的三种方法
- Ural1519 Formula 1 插头dp
- java文件的拷贝
- scala 反射
- 一种BaseDAO的写法
- 2016-7-10 杂感
- AngularJS 最常用的八种功能
- 7_6_E题 Crossing River [poj 1700]题解 (贪心)
- javascript类型系统——Math对象
- mysql 距离函数
- NOIP 2012 同余方程
- Ubuntu安装图片处理工具GIMP及其插件
- spring boot 图片上传后的图片读取路径在win与linux环境配置的差别
- Eclipse-调试
- ZooKeeper环境配置
- 微博接口知识整理
- jsp相对路径和绝对路径小谈