【题解】Codeforces 961G Partitions

【题解】Codeforces 961G Partitions

cf961G

好题啊哭了,但是如果没有不小心看了一下pdf后面一页的提示根本想不到

题意

已知\(U=\{w_i\}\),求:

\[\sum _{S}\sum_{s\in S}|s|\sum_{w \in s} w, S是U的一个k划分 \]

转换1

考虑这个\(|s|\)有点麻烦,稍微思考一下可以发现,我们最后的答案和\(w_i\)的分布没有关系,他们的贡献系数是一样的。答案只和他们的和有关。

转换2

考虑定位某个\(w_i\)对答案产生的贡献\(w_i \times p\),最后让\(\sum w\)乘上\(p\)就是答案。

然后就是喜闻乐见的套路时间了。这类与分配的集合的大小有关的计数题,可以用微扰法求出每一个元素的贡献。

考虑\(|s|\)每增大一,\(p\)就大一。考虑自己对于自己的贡献,这部分贡献就是\(\begin{Bmatrix}n\\k\end{Bmatrix}\)

然后考虑其他元素对自己的贡献,贡献就是钦定当前选定的一个其他元素和\(w_i\)在同一集合的划分方案数,此时可以用微扰法,先让其他\(n-1\)个元素自己先划分好,然后我在直接加入有\(w_i\)的那个集合,那么一个"其他元素"的贡献就是\(\begin{Bmatrix}n-1\\k\end{Bmatrix}\)。总共有\(n-1\)个其他元素。

所以最后的答案是

\[\sum w \times(\begin{Bmatrix}n\\k\end{Bmatrix}+(n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix}) \]

容斥球斯特林数即可。

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>


using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}
const int mod=1e9+7;
const int maxn=2e5+5;
int jc[maxn];
int inv[maxn];
int n,s,k,ans;
inline int Pow(const int&base,const int&p){
      register int ret=1;
      for(register int t=p,b=base%mod;t;t>>=1,b=1ll*b*b%mod)
	    if(t&1) ret=1ll*ret*b%mod;
      return ret;
}

inline int c(const int&n,const int&m){
      if(n<m)return 0;
      return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}


inline int stirlin(const int&n,const int&m){
      register int ret=0;
      for(register int t=0,delta;t<m;++t){
	    delta=1ll*c(m,t)*Pow(m-t,n)%mod;
	    if(t&1)delta=mod-delta;
	    ret=(ret+delta)%mod;
      }
      return 1ll*ret*inv[m]%mod;
}

int main(){
      
      jc[0]=inv[0]=1;
      for(register int t=1;t<maxn;++t)
	    jc[t]=1ll*jc[t-1]*t%mod,inv[t]=Pow(jc[t],mod-2);
      n=qr();k=qr();
      for(register int t=1;t<=n;++t)
	    s=(s+qr()%mod)%mod;
      if(s<0)s+=mod;
      ans=1ll*s*(stirlin(n,k)+1ll*(n-1)*stirlin(n-1,k)%mod)%mod;
      cout<<ans<<endl;
      return 0;
}

posted @ 2019-06-18 21:08  谁是鸽王  阅读(216)  评论(0编辑  收藏  举报