题意:求
∑
i
=
0
m
C
m
i
×
C
n
+
2
i
−
m
k
\sum_{i=0}^{m} C_{m}^{i}\times C_{n+2i-m}^{k}
i=0∑mCmi×Cn+2i−mk
其中
n
,
m
≤
1
0
9
n,m\le10^{9}
n,m≤109,
k
≤
300
k\le300
k≤300。共
T
T
T组数据,
T
≤
500
T\le500
T≤500。
题解:
推式子!
首先,我们想到
C
x
k
=
∏
i
=
0
k
−
1
x
−
i
k
−
i
C_{x}^{k}=\prod_{i=0}^{k-1}\frac{x-i}{k-i}
Cxk=i=0∏k−1k−ix−i
如果
k
k
k是一个常数,那么
C
x
k
C_{x}^{k}
Cxk可以表示成一个以
x
x
x为未知数的
k
k
k次多项式。
所以我们可以令
C
x
k
=
∑
i
=
1
k
a
i
x
i
C_{x}^{k}=\sum_{i=1}^{k}a_{i}x^{i}
Cxk=i=1∑kaixi
因为每组数据的
k
k
k都是给定的,所以我们可以在
O
(
k
2
)
O(k^2)
O(k2)的时间内算出
a
a
a。
∑
i
=
0
m
C
m
i
×
C
n
+
2
i
−
m
k
\ \ \ \ \sum_{i=0}^{m} C_{m}^{i}\times C_{n+2i-m}^{k}
∑i=0mCmi×Cn+2i−mk
=
∑
i
=
0
m
×
∑
j
=
1
k
a
j
×
(
n
+
2
i
−
m
)
j
=\sum_{i=0}^{m}\times\sum_{j=1}^{k}a_{j}\times(n+2i-m)^{j}
=∑i=0m×∑j=1kaj×(n+2i−m)j
=
∑
j
=
1
k
a
j
∑
i
=
0
m
(
n
+
2
i
−
m
)
j
=\sum_{j=1}^{k}a_{j}\sum_{i=0}^{m}(n+2i-m)^{j}
=∑j=1kaj∑i=0m(n+2i−m)j
我们二项式展开一下。
=
∑
j
=
1
k
a
j
∑
i
=
0
m
∑
t
=
0
j
C
j
t
(
n
−
m
)
t
(
2
i
)
j
−
t
=\sum_{j=1}^{k}a_{j}\sum_{i=0}^{m}\sum_{t=0}^{j}C_{j}^{t}(n-m)^{t}(2i)^{j-t}
=∑j=1kaj∑i=0m∑t=0jCjt(n−m)t(2i)j−t
=
∑
j
=
1
k
a
j
∑
t
=
0
j
C
j
t
(
n
−
m
)
t
×
2
j
−
t
∑
i
=
0
m
C
m
i
×
i
j
−
t
=\sum_{j=1}^{k}a_{j}\sum_{t=0}^{j}C_{j}^{t}(n-m)^{t}\times 2^{j-t}\sum_{i=0}^{m}C_{m}^{i}\times i^{j-t}
=∑j=1kaj∑t=0jCjt(n−m)t×2j−t∑i=0mCmi×ij−t
我们令
f
(
n
,
k
)
=
∑
i
=
0
n
C
n
i
×
i
k
f(n,k)=\sum_{i=0}^{n}C_{n}^{i}\times i^{k}
f(n,k)=∑i=0nCni×ik
则原式
=
∑
j
=
1
k
a
j
∑
t
=
0
j
C
j
t
(
n
−
m
)
t
×
2
j
−
t
f
(
m
,
j
−
t
)
=\sum_{j=1}^{k}a_{j}\sum_{t=0}^{j}C_{j}^{t}(n-m)^{t}\times 2^{j-t}f(m,j-t)
=∑j=1kaj∑t=0jCjt(n−m)t×2j−tf(m,j−t)。
我们看一看怎么求
f
f
f。
f
(
n
,
k
)
=
∑
i
=
0
n
C
n
i
×
i
k
\ \ \ \ \ f(n,k)=\sum_{i=0}^{n}C_{n}^{i}\times i^{k}
f(n,k)=∑i=0nCni×ik
=
∑
i
=
0
n
C
n
i
×
∑
j
=
0
k
s
(
k
,
j
)
×
C
i
j
×
j
!
=\sum_{i=0}^{n}C_{n}^{i}\times \sum_{j=0}^{k}s(k,j)\times C_{i}^{j} \times j!
=∑i=0nCni×∑j=0ks(k,j)×Cij×j!,
s
(
k
,
j
)
s(k,j)
s(k,j)为第二类斯特林数。
=
∑
j
=
0
k
s
(
k
,
j
)
×
j
!
∑
i
=
0
n
C
n
i
×
C
i
j
=\sum_{j=0}^{k}s(k,j)\times j!\sum_{i=0}^{n}C_{n}^{i}\times C_{i}^{j}
=∑j=0ks(k,j)×j!∑i=0nCni×Cij
=
∑
j
=
0
k
s
(
k
,
j
)
×
j
!
C
n
j
×
2
n
−
j
=\sum_{j=0}^{k}s(k,j)\times j!C_{n}^{j}\times2^{n-j}
=∑j=0ks(k,j)×j!Cnj×2n−j。
其中
C
n
i
×
C
i
j
C_{n}^{i}\times C_{i}^{j}
Cni×Cij就相当于先选
j
j
j个,剩下的随便选。
于是就可以预处理一下,愉快地计算啦!
总时间复杂度
O
(
T
k
2
)
O(Tk^{2})
O(Tk2)。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=305,mod=1000000007,inv2=500000004;
int t,n,m,k,s[N][N],a[N],jc[N],C[N][N],c[N],f[N],tmp[N];
int fastpow(int a,int x){
int res=1;
while(x){
if(x&1){
res=1LL*res*a%mod;
}
x>>=1;
a=1LL*a*a%mod;
}
return res;
}
int main(){
C[0][0]=s[0][0]=1;
for(int i=1;i<=300;i++){
C[i][0]=1;
for(int j=1;j<=i;j++){
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
s[i][j]=(s[i-1][j-1]+1LL*s[i-1][j]*j)%mod;
}
}
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&k);
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
jc[0]=c[0]=1;
for(int i=1;i<=k;i++){
jc[i]=1LL*jc[i-1]*i%mod;
c[i]=1LL*c[i-1]*(m-i+1)%mod*fastpow(i,mod-2)%mod;
}
f[0]=fastpow(2,m);
for(int i=1;i<=k;i++){
for(int j=0,base=f[0];j<=i;j++,base=1LL*base*inv2%mod){
f[i]=(f[i]+1LL*s[i][j]*jc[j]%mod*c[j]%mod*base)%mod;
}
}
a[0]=1;
for(int i=0;i<k;i++){
tmp[0]=0;
for(int j=1;j<=i+1;j++){
tmp[j]=(a[j-1]-1LL*i*a[j]%mod+mod)%mod;
}
for(int j=0;j<=i+1;j++){
a[j]=tmp[j];
}
}
for(int i=1;i<=k;i++){
a[i]=1LL*a[i]*fastpow(jc[k],mod-2)%mod;
}
int ans=0;
for(int i=1;i<=k;i++){
for(int j=0,b1=1,b2=fastpow(2,i);j<=i;j++,b1=1LL*b1*(n-m)%mod,b2=1LL*b2*inv2%mod){
ans=(ans+1LL*a[i]*C[i][j]%mod*b1%mod*b2%mod*f[i-j])%mod;
}
}
printf("%d\n",ans);
}
return 0;
}