您的位置:首页 > 其它

51Nod 1228 序列求和

2017-05-24 20:53 295 查看
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

 

数学问题 伯努利数 模板题

用伯努利数可以求自然数幂的和:

$ \sum_{i=1}^{n} i^2 =  \frac{1}{k+1}* \sum_{i=1}^{k+1} (C_{k+1}^{k+1-i} *B_{k+1-i}*(n+1)^i) $

伯努利数可以$O(n^2)$递推出来:

$ B_n=-\sum_{k=0}^{n-1} C_{n+1}^{k}*B_k$

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
const int mod=1e9+7;
const int mxn=2017;
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
return x*f;
}
LL B[mxn];
int c[mxn][mxn];
int ksm(int a,int k){
int res=1;
while(k){
if(k&1)res=(LL)res*a%mod;
a=(LL)a*a%mod;
k>>=1;
}
return res;
}
void init(){
for(int i=0;i<mxn;i++)c[i][0]=1;
for(int i=1;i<mxn;i++)
for(int j=1;j<mxn;j++)
c[i][j]=((LL)c[i-1][j-1]+c[i-1][j])%mod;
B[0]=1;
for(int i=1;i<mxn;i++){
for(int j=0;j<i;j++)
B[i]=(B[i]-c[i+1][j]*B[j])%mod;
int inv=ksm(i+1,mod-2);
B[i]=B[i]*inv%mod;
if(B[i]<0)B[i]+=mod;
}
return;
}
LL n;int k;
void calc(){
int res=0;
int tmp=(n+1)%mod;int bas=tmp;
for(int i=1;i<=k+1;i++){
res=((LL)res+(LL)c[k+1][i]*B[k+1-i]%mod*tmp%mod)%mod;
tmp=(LL)tmp*bas%mod;
}
int inv=ksm(k+1,mod-2);
res=(LL)res*inv%mod;
printf("%d\n",res);
return;
}
int main(){
int i,j;
init();
int T=read();
while(T--){
n=read();k=read();
calc();
}
return 0;
}

 

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