CF932E Team Work
求
\(1\le N\le 1e9, 1\le k \le 5000\)
\(N\)很大,考虑把\(N\)消成\(k\)表示的式子。
首先\(i^k\)可以转为第二类斯特林数和下降幂表示的式子
中间那个阶乘可以在循环的时候算掉(也就5000个)
求出第二类斯特林数这题就做完了。
去年十月份过这题的时候是想了一个奇怪的组合意义
原式表示从\(N\)个盒中选出\(i\)个 然后将\(k\)个球任意投入这\(i\)个盒子(允许盒子为空)的方案数之和
相当于把\(k\)个球分成\(j\)个集合(投入\(j\)个盒),剩下的\(N-j\)个空盒可能被选了,也可能没被选,故有\(2^{n-j}\)这一项。
至于阶乘项是\(\frac{N!}{(N-j)!}\),这代表从\(N\)个盒中选出\(j\)个,然后把他们排列一下。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e3 + 7;
#define ll long long
const ll md = 1e9 + 7;
ll n, k;
ll S[maxn][maxn], ans;
ll ksm(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) {
res = res * a % md;
}
a = a * a % md;
b >>= 1;
}
return res;
}
ll inv2;
int main() {
cin >> n >> k;
for (int i = 1; i <= 5000; i++) {
S[i][1] = S[i][i] = 1;
if (i > 1)
for (ll j = 1; j <= i; j++) {
S[i][j] = S[i-1][j-1] + j * S[i-1][j] % md;
S[i][j] %= md;
}
}
ll fac = n * ksm(2, n-1) % md;
inv2 = ksm(2, md - 2);
for (ll i = 1; i <= k; i++) {
ans = (ans + S[k][i] * fac % md) % md;
fac = fac * inv2 % md * (n - i + md) % md;
}
cout << ans << endl;
}