题解
这是一道纯粹的数学求导题目。
首先我们先写出要求的公式。
a
n
s
=
∑
r
=
1
n
C
n
r
r
k
ans = \sum_{r=1}^{n} C_n^{r}r^k
ans=∑r=1nCnrrk
乍一看,雾草好吓人,但是学过高等数学且稍有常识的人(不是我)可以看出,这个可以由某个式子不断乘x并求导得出来。
没错,稍有常识的人又可以看出来了,这个式子就是
(
1
+
x
)
n
(1+x)^n
(1+x)n
(
1
+
x
)
n
=
∑
r
=
0
n
C
n
r
x
r
(1+x)^n = \sum_{r=0}^{n}C_n^{r}x^r
(1+x)n=∑r=0nCnrxr
我们定义
f
0
=
d
d
x
(
1
+
x
)
n
=
n
(
1
+
x
)
n
−
1
f_0 = \frac{d}{dx}(1+x)^n = n(1+x)^{n-1}
f0=dxd(1+x)n=n(1+x)n−1
同时
f
0
(
x
)
=
∑
r
=
1
n
C
n
r
r
x
r
−
1
f_0(x) = \sum_{r=1}^{n} C_n^{r}rx^{r-1}
f0(x)=∑r=1nCnrrxr−1
定义
f
t
(
x
)
=
d
d
x
(
x
f
t
−
1
(
x
)
)
f_t(x) = \frac{d}{dx}(xf_{t-1}(x))
ft(x)=dxd(xft−1(x))
这样的话
f
k
−
1
(
x
)
=
∑
r
=
1
n
C
n
r
r
k
f_{k-1}(x) = \sum_{r=1}^{n} C_n^{r}r^k
fk−1(x)=∑r=1nCnrrk
那么我们要求的答案
a
n
s
=
f
k
−
1
(
0
)
(
1
)
ans = f_{k-1}^{(0)}(1)
ans=fk−1(0)(1)
我们知道
f
t
(
x
)
=
d
d
x
(
x
f
t
−
1
(
x
)
)
=
f
t
−
1
(
x
)
+
x
f
t
−
1
(
1
)
(
x
)
f_t(x) = \frac{d}{dx}(xf_{t-1}(x))=f_{t-1}(x)+xf_{t-1}^{(1)}(x)
ft(x)=dxd(xft−1(x))=ft−1(x)+xft−1(1)(x)
通过这个操作,
f
t
(
p
)
(
1
)
=
(
p
+
1
)
f
t
−
1
(
p
)
(
1
)
+
f
t
−
1
(
p
+
1
)
(
1
)
f_t^{(p)}(1) = (p+1)f_{t-1}^{(p)}(1)+f_{t-1}^{(p+1)}(1)
ft(p)(1)=(p+1)ft−1(p)(1)+ft−1(p+1)(1)
没错!这就是我们的递推公式!
定义
d
p
[
i
]
[
j
]
=
f
i
(
j
)
(
1
)
dp[i][j] = f_{i}^{(j)}(1)
dp[i][j]=fi(j)(1)
d
p
[
i
]
[
j
]
=
(
p
+
1
)
∗
d
p
[
t
−
1
]
[
p
]
+
d
p
[
t
−
1
]
[
p
+
1
]
dp[i][j] = (p+1)*dp[t-1][p]+dp[t-1][p+1]
dp[i][j]=(p+1)∗dp[t−1][p]+dp[t−1][p+1]
由于我们只需要
a
n
s
=
d
p
[
k
−
1
]
[
0
]
ans=dp[k-1][0]
ans=dp[k−1][0],那么就只需要
d
p
[
k
−
2
]
[
0...1
]
dp[k-2][0...1]
dp[k−2][0...1],…,只需要
d
p
[
0
]
[
0...
k
−
1
]
dp[0][0...k-1]
dp[0][0...k−1]
状态数
O
(
K
2
)
O(K^2)
O(K2)
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll N,k;
const ll mod = 1e9+7;
const int maxn = 5007;
ll dp[maxn][maxn],sum[maxn];
ll mod_pow(ll x,ll n){
ll ans = 1;
while(n){
if(n&1)
ans = ans * x % mod;
x = x*x%mod;
n >>= 1;
}
return ans;
}
int main(){
cin>>N>>k;
if(N == 1){
return 0*printf("1\n");
}
ll pre = N;
for(int t = 0;t < min(N,5005ll);++t){
dp[0][t] = pre*mod_pow(2,N-1-t)%mod;
pre = pre*(N-1-t)%mod;
}
for(int i = 1;i <= k;++i){
for(int j = 0;j <= k;++j){
dp[i][j] = ((j+1)*dp[i-1][j] + dp[i-1][j+1])%mod;
}
}
printf("%lld\n",dp[k-1][0]);
return 0;
}