题目描述
求\(\sum_{i=1}^{n}{(^n_i)i^k}\space mod\space10^9+7\)
思路
本题\(n\)的范围很大\((n\le10^9)\),但\(k\)在可接受的范围内\((k\le5000)\),我们可以尝试从\(k\)入手。
构造\((1+x)^n=\sum_{i=0}^n{(^n_i)x^i}\)
对等式两边求导并同乘\(x\),得
\[ nx(1+x)^{n-1}=\sum_{i=1}^n\big(^n_i\big)ix^i \]
重复操作,得
\[ x\frac{\mathrm{d}}{\mathrm{d}x}(nx(1+x)^{n-1})=\sum_{i=1}^n\big(^n_i\big)i^2x^i \]
我们发现,当操作\(k\)次并代入\(x=1\)时就是我们想要的答案。问题转化为求左式的值。但是我们难以直接得出一个复合函数的导数,因此考虑递推转移:令\(f[a][b][c]\)为\(x^b(1+x)^c\)经过a次操作的导数值,则我们要求的是\(f[k][0][n]\)
对\(x^b(1+x)^c\)进行一次操作,得:
\[ bx^b(1+x)^c+cx^{b+1}(1+x)^{c-1} \]
得到转移\(f[a][b][c]=b\times f[a-1][b][c] + c\times f[a-1][b+1][c-1]\)。这一转移可以用记忆化搜索来实现。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXK = 5000 + 10;
const int MOD = 1000000007;
ll f[MAXK][MAXK];
ll qpow(ll a, ll b)
{
ll ans = 1;
while (b) {
if (b & 1)
ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
ll dp(int a, int b, int c)
{
if (f[a][b] != -1)
return f[a][b];
ll& now = f[a][b];
now = 0;
if (a == 0)
return now = qpow(2, c);
if (c == 0)
return now = qpow(a, b);
return now = (b * dp(a - 1, b, c) + c * dp(a - 1, b + 1, c - 1)) % MOD;
}
int main()
{
ll n, k;
cin >> n >> k;
memset(f, -1, sizeof(f));
cout << dp(k, 0, n);
}
原文地址:https://www.cnblogs.com/erro/p/9037658.html
时间: 2024-11-08 21:28:40