[51nod1258]序列求和V4

补了一发伯努利数求自然数幂和,感觉挺好玩的...

具体数学上没有给构造,伯努利牛逼!真的不知道这个东西怎么“凭经验发现”

首先定义伯努利数$B_n$:$\sum\limits_{j=0}^m\binom{m+1}jB_j=[m=0]$

自然数幂求和$S_m(n)=\sum\limits_{k=0}^{n-1}k^m$

$S_{m+1}(n)+n^{m+1}=\sum\limits_{k=0}^{n-1}(k+1)^{m+1}=\sum\limits_{k=0}^{n-1}\sum\limits_{j=0}^{m+1}\binom{m+1}jk^j=\sum\limits_{j=0}^{m+1}\binom{m+1}jS_j(n)$

即是说$n^{m+1}=\sum\limits_{j=0}^m\binom{m+1}jS_j(n)$

现在我们要证$S_m(n)=\frac1{m+1}\sum\limits_{k=0}^m\binom{m+1}kB_kn^{m+1-k}$(这是伯努利“凭经验发现”的==)

对$m$归纳,假设$0\cdots m-1$都成立,设$\Delta=S_m(n)-\frac1{m+1}\sum\limits_{k=0}^m\binom{m+1}kB_kn^{m+1-k}$

接下来会用到$\binom{n+1}{m+1}=\frac{n+1}{m+1}\binom nm$和$\binom rm\binom mk=\binom rk\binom{r-k}{m-k}$

$\begin{aligned}n^{m+1}&=\sum\limits_{j=0}^m\binom{m+1}jS_j(n)\\&=\binom{m+1}m\Delta+\sum\limits_{j=0}^m\binom{m+1}j\frac1{j+1}\sum\limits_{k=0}^j\binom{j+1}kB_kn^{j+1-k}\\&=(m+1)\Delta+\sum\limits_{j=0}^m\sum\limits_{k=0}^j\binom{m+1}j\binom{j+1}{j-k}\frac{B_{j-k}}{j+1}n^{k+1}&k'\gets j-k\\&=(m+1)\Delta+\sum\limits_{j=0}^m\sum\limits_{k=0}^j\binom{m+1}j\binom{j+1}{k+1}\frac{B_{j-k}}{j+1}n^{k+1}\\&=(m+1)\Delta+\sum\limits_{k=0}^m\frac{n^{k+1}}{k+1}\sum\limits_{j=k}^m\binom{m+1}j\binom jkB_{j-k}\\&=(m+1)\Delta+\sum\limits_{k=0}^m\frac{n^{k+1}}{k+1}\binom{m+1}k\sum\limits_{j=k}^m\binom{m+1-k}{j-k}B_{j-k}\\&=(m+1)\Delta+\sum\limits_{k=0}^m\frac{n^{k+1}}{k+1}\binom{m+1}k\sum\limits_{j=0}^{m-k}\binom{m-k+1}jB_j\\&=(m+1)\Delta+\sum\limits_{k=0}^m\frac{n^{k+1}}{k+1}\binom{m+1}k[m-k=0]\\&=n^{m+1}+(m+1)\Delta\end{aligned}$

这说明$\Delta=0$,命题得证

扫描二维码关注公众号,回复: 2626036 查看本文章

然后就是求伯努利数,对定义式$\sum\limits_{j=0}^m\binom{m+1}jB_j=[m=0]$做代换$n=m+1$,得到$\sum\limits_j\binom njB_j=B_n+[n=1]$

考虑它的指数型生成函数$B(z)$,对应到上式即为$e^zB(z)=B(z)+z$,也就是说$B(z)=\frac z{e^z-1}$,直接求逆就可以了

这个模数==要拆系数FFT,不过因为数据范围不大跑得还不算慢

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double du;
const int mod=1000000007;
int mul(int a,int b){return a*(ll)b%mod;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
struct comp{
	du x,y;
	comp(du a=0,du b=0){x=a;y=b;}
};
comp operator+(comp a,comp b){return comp(a.x+b.x,a.y+b.y);}
comp operator-(comp a,comp b){return comp(a.x-b.x,a.y-b.y);}
comp operator*(comp a,comp b){return comp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
int rev[131072],N;
comp*w[17];
void pre(int n){
	int i,j,k;
	for(N=1,k=0;N<n;N<<=1)k++;
	for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	for(i=2,k=0;i<=N;i<<=1,k++){
		if(w[k]==0)w[k]=new comp[i>>1];
		for(j=0;j<i>>1;j++)w[k][j]=comp(cos(j*M_PI/(i/2)),sin(j*M_PI/(i/2)));
	}
}
void fft(comp*a,int on){
	int i,j,k,f;
	comp t;
	for(i=0;i<N;i++){
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(i=2,f=0;i<=N;i<<=1,f++){
		for(j=0;j<N;j+=i){
			for(k=0;k<i>>1;k++){
				t=w[f][k];
				t.y*=on;
				t=t*a[i/2+j+k];
				a[i/2+j+k]=a[j+k]-t;
				a[j+k]=a[j+k]+t;
			}
		}
	}
	if(on==-1){
		for(i=0;i<N;i++)a[i].x/=N;
	}
}
comp A[131072],B[131072],C[131072],D[131072];
void conv(int*a,int*b,int*c,int n){
	int i;
	comp t;
	pre(n<<1);
	memset(A,0,N<<4);
	memset(B,0,N<<4);
	memset(C,0,N<<4);
	memset(D,0,N<<4);
	for(i=0;i<n;i++){
		A[i]=a[i]>>15;
		B[i]=a[i]&32767;
		C[i]=b[i]>>15;
		D[i]=b[i]&32767;
	}
	fft(A,1);
	fft(B,1);
	fft(C,1);
	fft(D,1);
	for(i=0;i<N;i++){
		t=A[i]*D[i]+B[i]*C[i];
		A[i]=A[i]*C[i];
		C[i]=B[i]*D[i];
		B[i]=t;
	}
	fft(A,-1);
	fft(B,-1);
	fft(C,-1);
	for(i=0;i<n;i++)c[i]=((llround(A[i].x)%mod<<30)+(llround(B[i].x)%mod<<15)+llround(C[i].x)%mod)%mod;
}
int t1[65536];
void getinv(int*a,int*b,int n){
	if(n==1){
		b[0]=pow(a[0],mod-2);
		return;
	}
	int i;
	getinv(a,b,n>>1);
	conv(a,b,t1,n);
	for(i=0;i<n;i++)t1[i]=-t1[i];
	(t1[0]+=2)%=mod;
	conv(t1,b,b,n);
}
int fac[65537],rfac[65537],a[65536],b[65536];
int ch(int n,int k){return mul(fac[n],mul(rfac[k],rfac[n-k]));}
void getb(int n){
	int i;
	fac[0]=1;
	for(i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	rfac[n]=pow(fac[n],mod-2);
	for(i=n;i>0;i--)rfac[i-1]=mul(rfac[i],i);
	for(i=0;i<n;i++)a[i]=rfac[i+1];
	getinv(a,b,n);
	for(i=0;i<n;i++)b[i]=mul(b[i],fac[i]);
}
void work(){
	ll n;
	int m,i,s,t;
	scanf("%lld%d",&n,&m);
	n++;
	n%=mod;
	s=0;
	t=n;
	for(i=m;i>=0;i--){
		(s+=mul(mul(ch(m+1,i),b[i]),t))%=mod;
		t=mul(t,n);
	}
	s=mul(s,pow(m+1,mod-2));
	printf("%d\n",(s+mod)%mod);
}
int main(){
	int T;
	getb(65536);
	scanf("%d",&T);
	while(T--)work();
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9445906.html
今日推荐