【CF961G】Partitions

題面

洛谷

題解

顯然對於所有點對答案的貢獻都有一個相同的係數,設這個係數爲\(X\),那麼\(ans=X\sum w_i\)

枚舉一個點所在集合的大小,有
\[ \begin{aligned}\\ X&=\sum_{i=1}^n i{n-1\choose i-1}\begin{Bmatrix}n-i\\k-1\end{Bmatrix}\\ &=\sum_{i=1}^n i{n-1\choose i-1}\frac{1}{(k-1)!}\sum_{j=0}^{k-1}(-1)^j{k-1\choose j}(k-1-j)^{n-i}\\ &=\sum_{i=1}^n i{n-1\choose i-1}\sum_{j=0}^{k-1}\frac{(-1)^j}{j!}\frac{(k-j-1)^{n-i}}{(k-j-1)!}\\ &=\sum_{j=0}^{k-1}\frac{(-1)^j}{j!(k-j-1)!}\sum_{i=1}^n i {n-1\choose i-1}(k-j-1)^{n-i}\\ &=\sum_{j=0}^{k-1}\frac{(-1)^j}{j!(k-j-1)!}(\sum_{i=1}^n{n-1\choose i-1}(k-j-1)^{n-i}+\sum_{i=1}^n (i-1){n-1\choose i-1}(k-j-1)^{n-i})\\ &=\sum_{j=0}^{k-1}\frac{(-1)^j}{j!(k-j-1)!}(\sum_{i=1}^n{n-1\choose i-1}(k-j-1)^{n-i}+(n-1)\sum_{i=1}^n {n-2\choose i-2}(k-j-1)^{n-i})\\ &=\sum_{j=0}^{k-1}\frac{(-1)^j}{j!(k-j-1)!}((k-j)^{n-1}+(n-1)(k-j)^{n-2})\\ &=\sum_{j=0}^{k-1}\frac{(-1)^j}{j!(k-j-1)!}(k-j)^{n-2}(k-j+n-1)\\ \end{aligned} \]

這種推式子的方法比較不要腦子,還有一種要腦子的方法:

考慮什麼對一個點的貢獻,那麼他自己對自己的貢獻就爲\(\begin{Bmatrix}n\\k\end{Bmatrix}\)

別人對他的貢獻就是別人先分好然後他往別人分好的集合丟的貢獻,也就是\((n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix}\)

所以又有\(X=\begin{Bmatrix}n\\k\end{Bmatrix}+(n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix}\)

代碼

代碼是第二種方法的。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0; 
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
} 
const int MAX_N = 2e5 + 5, Mod = 1e9 + 7;
int fpow(int x, int y) { 
    int res = 1; 
    while (y) {
        if (y & 1) res = 1ll * res * x % Mod; 
        x = 1ll * x * x % Mod; 
        y >>= 1; 
    } 
    return res; 
} 
int fac[MAX_N], ifc[MAX_N];
int C(int n, int m) { 
    if (n < m) return 0;
    else return 1ll * fac[n] * ifc[n - m] % Mod * ifc[m] % Mod; 
} 
int N, K, w[MAX_N]; 
int S(int n, int m) { 
    int res = 0, p = 1; 
    for (int i = 0; i <= m; i++) { 
        res = (res + 1ll * p * C(m, i) % Mod * fpow(m - i, n)) % Mod; 
        p = Mod - p; 
    }
    res = 1ll * res * ifc[m] % Mod; 
    return res; 
} 
int main () { 
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin); 
#endif 
    N = gi(), K = gi();
    for (int i = 1; i <= N; i++) w[i] = gi(); 
    fac[0] = 1; for (int i = 1; i <= N; i++) fac[i] = 1ll * i * fac[i - 1] % Mod; 
    ifc[N] = fpow(fac[N], Mod - 2); 
    for (int i = N - 1; ~i; i--) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % Mod; 
    int ans = 0; 
    for (int i = 1; i <= N; i++) ans = (ans + w[i]) % Mod; 
    printf("%lld\n", 1ll * ans * (S(N, K) + 1ll * S(N - 1, K) * (N - 1) % Mod) % Mod); 
    return 0; 
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章