Live2D

题解 CF961G 【Partitions】

题目传送门

题目大意

给出\(n,k\),以及\(w_{1,2,..,n}\),定义一个集合\(S\)的权值\(W(S)=|S|\sum_{x\in S} w_x\),定义一个划分\(R\)的权值为\(\sum_{S\in R} W(S)\)。求出每种划分权值之和。

思路

这个题目有两种方法。一种就是直接从一眼式中暴推出答案,另外一种就是考虑组合意义,这里着重介绍后面一种。

我们发现\(W(S)\)实际上就等价于在\(S\)中的元素会对该集合中每个元素提供\(w_i\)的贡献。于是,我们考虑一个点会产生的贡献,首先对它自己会有\(w_i\begin{Bmatrix}n\\k\end{Bmatrix}\)的贡献,对其他点有\((n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix}w_i\)的贡献。这里解释一下后面那个,可以理解为先把\(n-1\)个分到\(k\)个盒子里(如果要产生贡献肯定要有跟它在同一个集合的元素),然后我可以加到这\(k\)里面任意一个,一共就是\(n-1\)个元素。

于是,我们得到答案就是:

\[(\begin{Bmatrix}n\\k\end{Bmatrix}+(n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix})(\sum_{i=1}^{n} w_i) \]

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define mod 1000000007
#define MAXN 200005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int n,k,w[MAXN],fac[MAXN],ifac[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int binom (int a,int b){return a >= b ? mul (fac[a],mul (ifac[b],ifac[a - b])) : 0;}
int qkpow (int a,int b){int res = 1;for (;b;b >>= 1,a = mul(a,a)) if (b & 1) res = mul (res,a) % mod;return res;}
int Sitelin (int n,int m){int res = 0;for (Int i = 0,tmp;i <= m;++ i) tmp = mul (binom (m,i),qkpow (i,n)),m - i & 1 ? (res = dec (res,tmp)) : (res = add (res,tmp));return 1ll * res * ifac[m] % mod;}

signed main(){
	read (n,k);fac[0] = 1;int sum = 0;
	for (Int i = 1;i <= n;++ i) read (w[i]),sum = add (sum,w[i]);
	for (Int i = 1;i <= k;++ i) fac[i] = mul (fac[i - 1],i);ifac[k] = qkpow (fac[k],mod - 2);for (Int i = k;i;-- i) ifac[i - 1] = mul (ifac[i],i);
	write (mul (sum,add (Sitelin (n,k),mul (n - 1,Sitelin (n - 1,k))))),putchar ('\n');
	return 0;
}
posted @ 2020-08-02 17:53  Dark_Romance  阅读(153)  评论(0编辑  收藏  举报