【CF961G】Partitions 第二类斯特林数

【CF961G】Partitions

题意:给出n个物品,每个物品有一个权值$w_i$,定义一个集合$S$的权值为$W(S)=|S|\sum\limits_{x\in S} w_x$,定义一个划分的权值为$V(R)=\sum\limits_{S\in R} W(S)$。求将n个物品划分成k个集合的所有方案的权值和。

$n,k\le 2\cdot 10^5,w_i\le 10^9$

题解:第二类斯特林数针是太好用辣!

显然每个物品都是独立的,所以我们只需要处理出每个物品被统计的次数即可,说白了就是求这个式子:

$\sum\limits_{i=1}^niC_{n-1}^{i-1}S_{n-i}^{k-1}$

暴力拆分斯特林数

$\sum\limits_{i=1}^niC_{n-1}^{i-1}S_{n-i}^{k-1}\\=\sum\limits_{i=1}^niC_{n-1}^{i-1}\sum\limits_{j=0}^{k-1}{(-1)^j\over j!}{(k-j-1)^{n-i}\over (k-j-1)!}\\=\sum\limits_{j=0}^{k-1}{(-1)^j\over j!(k-j-1)!}\sum\limits_{i=1}^niC_{n-1}^{i-1}(k-j-1)^{n-i}$

考虑后面那个东西

$\sum\limits_{i=1}^niC_{n-1}^{i-1}(k-j-1)^{n-i}\\=\sum\limits_{i=1}^nC_{n-1}^{i-1}(k-j-1)^{n-i}+\sum\limits_{i=1}^n(i-1)C_{n-1}^{i-1}(k-j-1)^{n-i}\\=\sum\limits_{i=1}^nC_{n-1}^{i-1}(k-j-1)^{n-i}+(n-1)\sum\limits_{i=1}^nC_{n-2}^{i-2}(k-j-1)^{n-i}\\=(k-j)^{n-1}+(n-1)(k-j)^{n-2}$

就完事啦!

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=1000000007;
typedef long long ll;
const int maxn=300010;
int n,k;
ll sum,ans;
ll jc[maxn],jcc[maxn],ine[maxn];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
	return ret*f;
}
inline ll pm(ll x,ll y)
{
	if(y<0)	return 1;
	ll z=1;
	while(y)
	{
		if(y&1)	z=z*x%P;
		x=x*x%P,y>>=1;
	}
	return z;
}
int main()
{
	n=rd(),k=rd();
	int i,j;
	for(i=1;i<=n;i++)	sum=(sum+rd())%P;
	ine[0]=ine[1]=jc[0]=jc[1]=jcc[0]=jcc[1]=1;
	for(i=2;i<=n;i++)	ine[i]=P-(P/i)*ine[P%i]%P,jc[i]=jc[i-1]*i%P,jcc[i]=jcc[i-1]*ine[i]%P;
	for(j=0;j<=k-1;j++)
	{
		ll tmp=((j&1)?-1:1)*jcc[j]*jcc[k-1-j]%P;
		ans=(ans+tmp*pm(k-j,n-2)%P*(k-j+n-1))%P;
	}
	ans=(ans+P)%P;
	printf("%lld",ans*sum%P);
	return 0;
}
posted @ 2018-04-05 19:22 CQzhangyu 阅读(...) 评论(...) 编辑 收藏