题目大意
设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[n]。
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;
}