传送门
解析:
稍微有点难的组合数学推导。。。
设
S k ( n ) = ∑ i = 1 n i k r i S_k(n)=\sum_{i=1}^ni^kr^i Sk(n)=i=1∑nikri
现在我们要求这个鬼畜的式子。。。
(面部疯狂抽搐)
首先把 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)(r−1)Sk(n)===i=1∑nikrii=2∑n+1(i−1)krirn+1nk−r+i=2∑nri[(i−1)k−ik]
把后面这一截拿出来算,直接二项式展开:
∑ 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=2∑nri[(i−1)k−ik]i=2∑nrij=0∑k−1(jk)ij(−1)k−jj=0∑k−1(jk)(−1)k−ji=2∑n(riij)
发现最后这个东西形成的递推式: ∑ i = 2 n ( r i i j ) = S j ( n ) − r \sum_{i=2}^n(r^ii^j)=S_j(n)-r i=2∑n(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;
}