您的位置:首页 > 其它

[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≤5000

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