您的位置:首页 > 其它

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

2017-10-05 15:48 246 查看
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


相关问题


序列求和 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));
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: