2019.04.02【51nod1229】序列求和 V2(组合数学)

传送门


解析:

稍微有点难的组合数学推导。。。

S k ( n ) = ∑ i = 1 n i k r i S_k(n)=\sum_{i=1}^ni^kr^i Sk(n)=i=1nikri

现在我们要求这个鬼畜的式子。。。

(面部疯狂抽搐)

首先把 r = 1 r=1 r=1 r = 0 r=0 r=0的情况处理了, r = 1 r=1 r=1就是自然数的幂和,随便怎么做都行, r = 0 r=0 r=0那答案就是 0 0 0,注意这里说的是取模后的。

废话少说,直接开始推导:

S k ( n ) = ∑ i = 1 n i k r i r S k ( n ) = ∑ i = 2 n + 1 ( i − 1 ) k r i ( r − 1 ) S k ( n ) = r n + 1 n k − r + ∑ i = 2 n r i [ ( i − 1 ) k − i k ] \begin{aligned} S_k(n)&=&&\sum_{i=1}^ni^kr^i\\ rS_k(n)&=&&\sum_{i=2}^{n+1}(i-1)^kr^i\\ (r-1)S_k(n)&=&&r^{n+1}n^k-r+\sum_{i=2}^nr^i[(i-1)^k-i^k] \end{aligned} Sk(n)rSk(n)(r1)Sk(n)===i=1nikrii=2n+1(i1)krirn+1nkr+i=2nri[(i1)kik]

把后面这一截拿出来算,直接二项式展开:

∑ i = 2 n r i [ ( i − 1 ) k − i k ] = ∑ i = 2 n r i ∑ j = 0 k − 1 ( k j ) i j ( − 1 ) k − j = ∑ j = 0 k − 1 ( k j ) ( − 1 ) k − j ∑ i = 2 n ( r i i j ) \begin{aligned} &\sum_{i=2}^{n}r^i[(i-1)^k-i^k]\\ =&\sum_{i=2}^nr^i\sum_{j=0}^{k-1}{k\choose j}i^j(-1)^{k-j}\\ =&\sum_{j=0}^{k-1}{k\choose j}(-1)^{k-j}\sum_{i=2}^n(r^ii^j) \end{aligned} ==i=2nri[(i1)kik]i=2nrij=0k1(jk)ij(1)kjj=0k1(jk)(1)kji=2n(riij)

发现最后这个东西形成的递推式: ∑ i = 2 n ( r i i j ) = S j ( n ) − r \sum_{i=2}^n(r^ii^j)=S_j(n)-r i=2n(riij)=Sj(n)r

直接 O ( k 2 ) O(k^2) O(k2)递推就好了。


代码:

#include<bits/stdc++.h>
#define ll long long 
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline ll getint(){
		re char c;
		while(!isdigit(c=gc()));re ll num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num; 
	}
}
using namespace IO;

using std::cout;
using std::cerr;

cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int quickpow(int a,int b,int res=1){
	while(b){
		if(b&1)res=mul(res,a);
		a=mul(a,a);
		b>>=1;
	}
	return res;
}
inline int qpow(ll a,ll b){
	return quickpow(a%mod,b%(mod-1));
}
template<class ...Args>
inline int add(int a,Args &...args){return add(a,add(args...));}
template<class ...Args>
inline int mul(int a,Args &...args){return mul(a,mul(args...));}

cs int P=2e3+3;
int fac[P],ifac[P],inv[P];
inline int C(int n,int m){return mul(fac[n],ifac[m],ifac[n-m]);}
int B[P];
inline void init(){
	B[0]=fac[0]=fac[1]=ifac[0]=ifac[1]=inv[0]=inv[1]=1;
	for(int re i=2;i<P;++i){
		fac[i]=mul(fac[i-1],i);
		inv[i]=mul(inv[mod%i],mod-mod/i);
		ifac[i]=mul(ifac[i-1],inv[i]);
	}
	for(int re i=1;i<P;++i){
		for(int re j=0;j<i;++j)B[i]=add(B[i],mul(B[j],C(i+1,j)));
		B[i]=dec(0,mul(B[i],inv[i+1]));
	}
}

ll n;int k,r;

inline int solve1(){
	++n%=mod;int ans=0,now=n;
	for(int re i=k;~i;--i,now=mul(now,(int)n))ans=add(ans,mul(C(k+1,i),now,B[i]));
	return mul(ans,inv[k+1]);
}

int s[P];
inline int solve2(){
	int b=qpow(r,n+1),iv=qpow(r-1,mod-2);
	s[0]=mul(dec(b,r),iv);
	for(int re i=1,now=n%mod;i<=k;++i,now=mul(now,(int)(n%mod))){
		s[i]=dec(mul(b,now),r);
		for(int re j=0;j<i;++j){
			int val=mul(C(i,j),dec(s[j],r));
			s[i]=((i-j)&1)?dec(s[i],val):add(s[i],val);
		}
		s[i]=mul(s[i],iv);
	}
	return s[k];
}

signed main(){
	init();
	int q=getint();
	while(q--){
		n=getint(),k=getint(),r=getint()%mod;
		if(r==0)cout<<0<<"\n";
		else if(r==1)cout<<solve1()<<"\n";
		else cout<<solve2()<<"\n"; 
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值