题解 [CF961G] Partitions

题面

解析

首先我们观察这个定义,

可以发现每个元素在统计答案时是平等的,

也就是单个元素的权值对答案没有特别的影响.

设元素权值为\(w[i]\),

那么我们就可以知道答案是\(\sum_{i=1}^nw[i]\)乘上一个系数.

而我们再次观察问题中的一个式子\(\left\vert s \right\vert*\sum\limits_iw[i]\),

实际上也就是把\(\sum\limits_iw[i]\)加了\(\left\vert s \right\vert\)次.

所以我们可以把它看成是集合中的每个元素都对答案造成了\(\sum\limits_iw[i]\)的贡献.

而贡献有两种情况:

  1. 元素自己给自己贡献

    这显然是总情况数\(S(n,k)\),\(S\)为第二类斯特林数.

  2. 元素\(j\)给\(i\)贡献(\(j!=i\))

    这里的情况数是\((n-1)*S(n-1,k)\).

    我们可以理解为先把除了\(i\)的元素分好,再把\(i\)加到其中一个里面.

    因为有还\(n-1\)个元素所以要乘\((n-1)\).

最后,答案就是\((S(n,k)+(n-1)*S(n-1,k))*\sum_{i=1}^nw[i]\).

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define int ll
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std; inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
} const int N=200001;
const int Mod=1000000007;
int n,m,sum,f,jc[N]; inline int fp(int a,int b){
int ret=1;
while(b){
if(b&1) ret=(ll)ret*a%Mod;
a=(ll)a*a%Mod;b>>=1;
}
return ret;
} inline int inv(int x){
return fp(x,Mod-2);
} inline int stir(int n,int k){
int ret=0;
for(int j=0;j<k;j++) ret=(ret+fp(k-j,n)*inv(jc[j])%Mod*inv(jc[k-j])*((j&1)? -1:1))%Mod;
return ret;
} signed main(){
n=read();m=read();jc[0]=1;
for(int i=1;i<=n;i++) sum=(sum+read())%Mod;
for(int i=1;i<=m;i++) jc[i]=jc[i-1]*i%Mod;
int ans=sum*(stir(n,m)+stir(n-1,m)*(n-1)%Mod)%Mod;
printf("%lld\n",(ans+Mod)%Mod);
return 0;
}
上一篇:ZOJ 3965 Binary Tree Restoring


下一篇:FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ