求
S(n,k)=∑i=1nik
可以
O(k2)
递推。
用伯努利数可以做到
O(k)
∑i=1nik=1k+1∑i=1k+1Cik+1∗Bk+1−i∗(n+1)i
而伯努利数满足
B0=1
∑k=0nCkn+1Bk=0
因此我们有伯努利数的递推式:
Bn=−1n+1∑i=0n−1Cin+1∗Bi
因此预处理组合数,逆元,伯努利数即可。
O(T∗K)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 2010
#define mod 1000000007
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline ll read(){
ll x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int C[N][N],inv[N],B[N],n,K;
inline int cal(){
int res=0,tmp=n+1;
for(int i=1;i<=K+1;++i)
(res+=(ll)C[K+1][i]*B[K+1-i]%mod*tmp%mod)%=mod,tmp=(ll)tmp*(n+1)%mod;
res=(ll)res*inv[K+1]%mod;return res;
}
int main(){
// freopen("a.in","r",stdin);
int tst=read();inv[1]=1;
for(int i=2;i<=2001;++i) inv[i]=(ll)inv[mod%i]*(mod-mod/i)%mod;
for(int i=0;i<=2001;++i) C[i][0]=1;
for(int i=1;i<=2001;++i)
for(int j=1;j<=i;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
B[0]=1;
for(int i=1;i<=2000;++i){
for(int j=0;j<=i-1;++j) (B[i]+=(ll)C[i+1][j]*B[j]%mod)%=mod;
B[i]=(ll)B[i]*inv[i+1]*-1%mod;if(B[i]<0) B[i]+=mod;
}while(tst--){
n=read()%mod;K=read();printf("%d\n",cal());
}return 0;
}
版权声明:本文为Icefox_zhx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。