51nod1228 序列求和 (伯努利数)

来源:互联网 发布:云南山歌软件下载 编辑:程序博客网 时间:2024/06/08 18:40

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示例
35 34 24 1
Output示例
2253010
相关问题
序列求和 V2 
320
 
序列求和 V5 
1280
 
序列求和 V4 
1280
 
序列求和 V3 
320
李陶冶 (题目提供者)


#include<bits/stdc++.h>using namespace std;typedef long long LL;const LL MOD=1e9+7;const int maxn=4e3+10;#define CLR(a) memset(a,0,sizeof(a))//使得一个数标准化,最稳的方法就是(取模+模后)再 取模 #define DEAL(a) ((a%MOD+MOD)%MOD)  LL B[maxn],Pow[maxn],n,k,C[maxn][maxn];LL quickpow(LL a,LL b){a%=MOD;LL ans=1;while(b){if(b&1) ans=ans*a%MOD;a=a*a%MOD;b>>=1;}return DEAL(ans);}void GetC(){CLR(C);for(int i=0;i<maxn;i++){C[i][0]=1;for(int j=1;j<=i;j++){C[i][j]=C[i-1][j]+C[i-1][j-1];C[i][j]%=MOD;}}}LL GetInv(LL x){return quickpow(x,MOD-2);//费马小定理 }void GetB(){B[0]=1;for(int i=1;i<maxn-1;i++) {LL temp=0;for(int j=0;j<i;j++){temp+=C[i+1][j]*B[j];temp%=MOD;}temp=temp*-GetInv(i+1)%MOD;B[i]=DEAL(temp);}}int main(){GetC();//预处理组合数 GetB();//预处理伯努利数 int T;scanf("%d",&T);while(T--){Pow[0]=1;scanf("%lld%lld",&n,&k);for(int i=1;i<=k+1;i++) Pow[i]=(n+1)%MOD*Pow[i-1]%MOD;LL ans=0;for(int i=1;i<=k+1;i++) ans+=C[k+1][i]*B[k+1-i]%MOD*Pow[i]%MOD;ans=DEAL(ans);ans=ans*GetInv(k+1)%MOD;printf("%lld\n",DEAL(ans));}}