題庫連接c++
給你 \(n\) 個不一樣的元素組成的集合 \(R\) ,每一個元素有一個權值 \(w\) 。對於一個子集集合 \(S\) ,它的價值爲 \(W(S)=|S|\cdot\sum\limits_{i\in S}w_i\) 。現要求將該集合 \(R\) 劃分紅 \(k\) 個互不相交的非空子集 \(S_i\) 。定義一種劃分的價值爲 \(\sum\limits_{i=1}^k W(S_i)\) 。求全部劃分的價值和。對大質數取模。ui
\(1\leq k\leq n\leq 2\cdot 10^5\)spa
容易發現對於不一樣的元素,他對答案的貢獻本質是相同的。即咱們只要求出某一種元素在全部方案中出現的次數 \(sum\) ,那麼答案就是 \(sum\times \sum\limits_{i=1}^n w_i\) 。code
考慮如何求 \(sum\) 。ip
容易發現它對 \(sum\) 的貢獻只與和它被劃分到同一集合的元素的個數有關。get
綜上答案就是 \((S(n-1,k-1)+(n+k-1)\cdot S(n-1, k))\cdot\sum\limits_{i=1}^n w_i\) 。it
\(S(n,m)\) 用通項公式計算就行了。io
#include <bits/stdc++.h> using namespace std; const int N = 2e5, yzh = 1e9+7; int x, n, k, inv[N+5]; int quick_pow(int a, int b) { int ans = 1; while (b) { if (b&1) ans = 1ll*ans*a%yzh; a = 1ll*a*a%yzh, b >>= 1; } return ans; } int S(int n, int m) { int ans = 0; for (int i = 0; i <= m; i++) { int t = 1ll*inv[i]*inv[m-i]%yzh*quick_pow(m-i, n)%yzh; if (i&1) (ans -= t) %= yzh; else (ans += t) %= yzh; } return ans; } void work() { scanf("%d%d", &n, &k); inv[0] = inv[1] = 1; for (int i = 2; i <= k; i++) inv[i] = -1ll*yzh/i*inv[yzh%i]%yzh; for (int i = 1; i <= k; i++) inv[i] = 1ll*inv[i-1]*inv[i]%yzh; int sum = 0; for (int i = 1; i <= n; i++) scanf("%d", &x), (sum += x) %= yzh; int ans = (S(n-1, k-1)+1ll*(n+k-1)*S(n-1, k)%yzh)%yzh; ans = 1ll*ans*sum%yzh; printf("%d\n", (ans+yzh)%yzh); } int main() {work(); return 0; }