法一
每个数的贡献系数是一样的,我们枚举当前数所在集合的大小,那么答案为((sumlimits_{i=1}^nw_i)(sumlimits_{i=1}^ni{n-1choose i-1}left{n-iatop k-1
ight}))。
可以利用多项式算法求出,比较复杂。
法二
我们设现在要求出(x)的贡献系数,划分好集合之后,当前情况的贡献就是(x)所在集合(S)的大小。
(|S|)可以分为(x)的贡献与其它数的贡献。
(x)的贡献:在任何一个划分方案中都有(1)的贡献,因此总贡献为(left{natop k
ight})。
其它数贡献:显然(n-1)个其它数的贡献都是一样的,因此我们现在考虑(y)的贡献。(y)有(1)的贡献当且仅当(x,y)在同一个集合,方案数为(left{n-1atop k
ight})。因此总贡献为((n-1)left{n-1atop k
ight})。
那么(x)的贡献系数就是(left{natop k
ight}+(n-1)left{n-1atop k
ight}),答案就是((sumlimits_{i=1}^nw_i)(left{natop k
ight}+(n-1)left{n-1atop k
ight}))。
#include<cstdio>
const int N=200007,P=1000000007;
int ifac[N];
int read(){int x;scanf("%d",&x);return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
void dec(int&a,int b){a-=b,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int b){int r=1;for(;b;b>>=1,a=mul(a,a))if(b&1)r=mul(a,r);return r;}
int S(int n,int k){int r=0;for(int i=0;i<=k;++i) (i&1? dec:inc)(r,1ll*ifac[i]*pow(k-i,n)%P*ifac[k-i]%P);return r;}
int main()
{
int n=read(),k=read(),sum=0;ifac[0]=1;
for(int i=1;i<=n;++i) inc(sum,read());
for(int i=1;i<=n;++i) ifac[i]=mul(ifac[i-1],pow(i,P-2));
printf("%d",mul(sum,(S(n,k)+(n-1ll)*S(n-1,k))%P));
}