CF932E: Team Work 题解(第二类斯特林数)

CF932E: Team Work 题解

E:

题意:输入 \(n,k\), 求 \(\sum\limits_{i=1}^nC_n^i·i^k\)。(n<=1e9,k<=5000)

非常简短的题面,但是威力惊人啊,数学不好根本不知道如何下手,推着推着式子发现越推越复杂。

Solution1:求导

我们先把我们以前会的东西列出来:

①:\(\sum\limits_{i=0}^nC_n^i=2^n\)

②:\(\sum\limits_{i=1}^nC_n^i=2^n-1\)

③:\(\sum\limits_{i=1}^{n}C_n^i·x^i=(1+x)^n-1\)(二项式展开)

④:\(\sum\limits_{i=1}^nC_n^i·i=n·2^{n-1}\)

第四个式子左边是什么呢,就是 \(n\) 个数任意选,把每种情况选中的个数加起来。因为每个位置对总和贡献相同,都在 \(2^{n-1}\) 种情况中出现过,因此总和为 \(n·2^{n-1}\)

但这道题要加的不是 \(i\),而是 \(i^k\)\(k\) 是一个不变的数字,和③式形式不是很一样(其实是很不一样)。

这时候要用到我们的求导大法,将③式左右同时对 \(x\) 求导,得⑤式:

⑤:\(\sum\limits_{i=1}^nC_n^i·ix^{i-1}=n(1+x)^{n-1}\)

为什么下标 \(i\) 要从 \(1\) 开始,因为 \(x^0\) 求导完是 \(0\) 而不是 \(x^{-1}\) ,我们避免这种讨论,所以让多项式指数一直大于 0。

然后你会发现④式其实就是⑤式 \(x=1\) 的情况。我们有了一个思路:通过求导,使得左边的系数变成 \(i^k\) ,这里的 \(i\)\(k\) 都与 \(x\) 无关,我们最终代入 \(x=1\) 便可以消去 \(x\)

为了再次求导产生 \(i\) ,我们将两边乘上 \(x\),左式变为 \(\sum\limits_{i=1}^nC_n^i·ix^i\)。这样不断地求导再乘 \(x\),最终可推出我们想求的式子。

\(\sum\limits_{i=1}^nC_n^i·x^i=(1+x)^n-1\)

\(\sum\limits_{i=1}^nC_n^i·i·x^i=nx(1+x)^{n-1}\)

\(\sum\limits_{i=1}^nC_n^i·i^2·x^i=nx(1+x)^{n-1}+n(n-1)x^2(1+x)^{n-2}\)

......

\(\sum\limits_{i=1}^nC_n^i·i^k·x^i=a_1x(1+x)^{n-1}+a_2x^2(1+x)^{n-2}+a_3x^3(1+x)^{n-3}+...+a_kx^k(1+x)^{n-k}\)

\(\sum\limits_{i=1}^nC_n^i·i^k=a_12^{n-1}+a_22^{n-2}+a_32^{n-3}+...+a_k2^{n-k}\)

我们用自己的猴力计算,把右边求导再乘 \(x\),发现每一项的系数是可以递推求出的 : \(a_{i,j} = a_{i-1,j-1}*(n+1-j)+a_{i-1,j}*j\)。复杂度 \(k^2\)

最后还要注意到当 \(n<k\) 时,右式不足以以这种形式导 k 次,所以 n 比较小的时候直接暴力求就行。

const ll p=1000000007;
ll T;
ll n,k;
ll ans,a[2][N];
ll f[N],ni[N];

inline ll ksm(ll aa,ll bb) {
    ll sum = 1;
    while(bb) {
        if(bb&1) sum = sum * aa %p;
        bb >>= 1; aa = aa * aa %p;
    }
    return sum;
}

inline ll C(ll aa,ll bb) { return f[aa] * ni[bb] %p * ni[aa-bb] %p; }

void qiu() {
    f[0] = ni[0] = 1;
    for(ll i=1;i<=N-10;i++) f[i] = f[i-1] * i %p;
    ni[N-10] = ksm(f[N-10],p-2);
    for(ll i=N-11;i>=1;i--) ni[i] = ni[i+1] * (i+1) %p;
}

int main() {
    qiu();
    n = read(); k = read();
    if(n<=k+10) {
        for(ll i=1;i<=n;i++) (ans += C(n,i) * ksm(i,k) %p) %= p;
        cout<<(ans%p+p)%p;
        return 0;
    }
    a[1][1] = n;
    for(ll i=2;i<=k;i++) {
        ll cl = i&1;
        for(ll j=1;j<=i;j++)
            a[cl][j] = (a[cl^1][j-1] * (n+1-j) %p + a[cl^1][j] * j %p) %p;
    }
    for(ll i=1;i<=k;i++) (ans += a[k&1][i] * ksm(2,n-i) %p) %= p;
    cout<<(ans%p+p)%p;
    return 0;
}

突然发现这题不就是2020省选D1T2组合数问题吗,数据范围也是k^2,当时同省很多大佬都会做的,退役是完全因为自己菜,只能说相见恨晚。


Solution2:第二类斯特林数

此题可以用斯特林数进行推导,可惜模数不能NTT,因此也只好用 n 方递推求斯特林数。

事实上在上面求系数 a 时的递推式就是斯特林数乘上一个下降幂。


先来个纯数学推法:

由小球放盒子可以得到一个拆解 \(i^k\) 的公式:见此博客二级标题“经典应用”

\(i^k=\sum\limits_{j=1}^kS_k^jC^j_i·j!\)

枚举上界到 k 或到 i 其实是一样的,因为后面的两个括号暗示了 \(j<=min(k,i)\),否则为 0,因为这题 k 比 i 上限要小,为了方便后续推导我们写成 k。

\(\sum\limits_{i=0}^nC_n^i·i^k\)

\(=\sum\limits_{i=0}^nC_n^i\sum\limits_{j=1}^kS_k^jC_i^j·j!\)

\(=\sum\limits_{j=1}^kS_k^j·j!\sum\limits_{i=0}^nC_n^iC_i^j\)

\(=\sum\limits_{j=1}^kS_k^j·j!\sum\limits_{i=0}^n\frac{n!}{i!(n-i)!}·\frac{i!}{j!(i-j)!}\)

\(=\sum\limits_{j=1}^kS_k^j\sum\limits_{i=0}^n\frac{n!}{(n-i)!(i-j)!}\)

n 太大没法求后面的和,但是一个类似组合数求和的形式让我们想到二项式,我们往二项式去凑,希望可以把组合数求和化为幂次的形式.

而将右边化为组合数就需要有 \(\frac{(A+B)!}{A!B!}\) 的形式,我们发现下面两项加起来刚好能把 i 消掉,很妙。

\(=\sum\limits_{j=1}^kS_k^j\sum\limits_{i=0}^n\frac{(n-j)!}{(n-i)!(i-j)!}·\frac{n!}{(n-j)!}\)

\(=\sum\limits_{j=1}^kS_k^j·\frac{n!}{(n-j)!}\sum\limits_{i=0}^nC_{n-j}^{i-j}\)

右边求和虽然长得丑但也是二项式求和的形式,\(i-j<0\) 时组合数的值应当为 0。

\(=\sum\limits_{j=1}^kS_k^j·\frac{n!}{(n-j)!}2^{n-j}\)

本来可以 klogk 求 第二类斯特林数(行),可惜模数不喜欢。

Solution3:还是第二类斯特林数

litble佬的题解

担心上面的推导过程写错,或者卡住?litble佬给出了一个省去好多步骤的推法,但是她的描述有点太简略了,我详细写下。

转化题意,题目相当于:从 n 个盒子里选 i 个,然后将 k 个球任意装进选择的 i 个盒子中(可为空),求总方案数。

我们也枚举盒子,但是我们不枚举选择的 i 个,而是枚举装了球的盒子数量 j (也就是不可为空)。

我们考虑有多少种情况是 j 个盒子装了球:\(C_n^j\) 先选 j 个盒子,其他的 n-j 个盒子是否被选进那 i 个当中无所谓,因此一共有 \(2^{n-j}\) 种情况满足:这 j 个盒子装了球。

答案为:\(\sum\limits_{j=1}^kF(k,j)·C_n^j·2^{n-j}\)\(F(k,j)\) 表示 k 个球装进 j 个盒子,每个盒子不为空的方案,显然 \(F(k,j)=S_k^j·j!\)

所以最终答案为:

\(\sum\limits_{j=1}^kS_k^j·j!·C_n^j·2^{n-j}\)

\(=\sum\limits_{j=1}^kS_k^j·\frac{n!}{(n-j)!}·2^{n-j}\)

\(=\sum\limits_{j=1}^kS_k^j·n^{\underline{j}}·2^{n-j}\)

虽然 n 很大没法求阶乘,但是转化为下降幂的形式后,因为指数 j 上限为 k,因此可以暴力乘出结果。

posted @ 2024-02-23 20:44  maple276  阅读(24)  评论(0编辑  收藏  举报