CF932E Team Work

\[\sum_{i=1}^{N}C_N^ii^k \]

\(1\le N\le 1e9, 1\le k \le 5000\)

\(N\)很大,考虑把\(N\)消成\(k\)表示的式子。

首先\(i^k\)可以转为第二类斯特林数和下降幂表示的式子

\[\begin{aligned} &\sum_{i=0}^{N}C_N^ii^k \\ =&\sum_{i=0}^NC_N^i\sum_{j=0}^{k}S_k^jj!C_i^j \\ =&\sum_{j=0}^kS_k^jj!\sum_{i=0}^NC_N^iC_i^j \\ =&\sum_{j=0}^kS_k^jj!\sum_{i=0}^N\frac{N!}{(N-i)!j!(i-j)!} \\ =&\sum_{j=0}^kS_k^jj!\frac{N!}{j!(N-j)!}\sum_{i=0}^N\frac{(N-j)!}{(N-i)!(i-j)!} \\ =&\sum_{j=0}^kS_k^jj!\frac{N!}{j!(N-j)!}\sum_{i=j}^N\frac{(N-j)!}{(N-i)!(i-j)!} \\=&\sum_{j=0}^kS_k^jj!C_N^j\sum_{i=j}^{N}C_{N-j}^{i-j} \\=&\sum_{j=0}^kS_k^jj!C_N^j2^{N-j} \\=&\sum_{j=0}^kS_k^j\frac{N!}{(N-j)!}2^{N-j} \end{aligned} \]

中间那个阶乘可以在循环的时候算掉(也就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;
}