引理(1):
[kdbinom{n}{k}=ndbinom{n-1}{k-1}
]
易证
引理(2):
[sumlimits_{i=0}^{n}dbinom{n}{i}(k-1)^{n-i}=k^n
]
证明:
等式右侧的意义为长度为(n)的序列,每个位置填([1,k])的方案数
左侧意义为枚举(k)的个数(i),从(n)个位置中选出(i)个作为(k),其他位置从([1,k-1])中选择
正题:
不难发现每个元素的贡献的系数是相同的
枚举(i)所在集合大小,有一个暴力的式子
[ans=sumlimits_{i=1}^{n}w_isumlimits_{s=1}^{n}sdbinom{n-1}{s-1}egin{Bmatrix}n-s\k-1end{Bmatrix}
]
只考虑不包含(w_i)的部分
[=sumlimits_{s=1}^{n}sdbinom{n-1}{s-1}sumlimits_{i=0}^{k-1}frac{(-1)^i}{i!}frac{(k-i-1)^n-s}{(k-i-1)!}
]
[=sumlimits_{i=0}^{k-1}frac{(-1)^i}{i!(k-i-1)!}sumlimits_{s=1}^{n}sdbinom{n-1}{s-1}(k-i-1)^{n-s}
]
只考虑(sumlimits_{s=1}^{n}sdbinom{n-1}{s-1}(k-i-1)^{n-s})
[=sumlimits_{s=1}^{n}dbinom{n-1}{s-1}(k-i-1)^{n-s}+sumlimits_{s=1}^{n}(s-1)dbinom{n-1}{s-1}(k-i-1)^{n-s}
]
根据引理(1)
[=sumlimits_{s=1}^{n}dbinom{n-1}{s-1}(k-i-1)^{n-s}+(n-1)sumlimits_{s=1}^{n}dbinom{n-2}{s-2}(k-i-1)^{n-s}
]
根据引理(2)
[=(k-i)^{n-1}+(n-1)(k-i)^{n-2}
]
[=(k-i)^{n-2}(k-i+n-1)
]
[sumlimits_{i=0}^{k-1}frac{(-1)^i}{i!(k-i-1)!}sumlimits_{s=1}^{n}sdbinom{n-1}{s-1}(k-i-1)^{n-s}=sumlimits_{i=0}^{k-1}frac{(-1)^i(k-i)^{n-2}}{i!(k-i-1)!}(k-i+n-1)
]
此时已经可以(O(klogk))解决了
这种东西能推的出来?
但是我们有更简单的方法
当(w_i)处于一个集合的时候,可以看作集合中的每个数字对(w_i)造成了(1)倍的贡献
自己对自己的贡献显然是(egin{Bmatrix}n\kend{Bmatrix})
考虑一个其他数对自己的贡献,相当与一个数字和自己在一个集合的方案数,可以看作先把(n-1)个数划分出(k)个集合,自己再加入那个数所在的集合(egin{Bmatrix}n-1\kend{Bmatrix})
所以
[ans=sumlimits_{i=1}^{w_i}egin{Bmatrix}n\kend{Bmatrix}+(n-1)egin{Bmatrix}n-1\kend{Bmatrix}
]
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=2e5+10,p=1e9+7;
int n,k,ans,sum;
int inv[N],fac[N],ifac[N];
inline void init(int n)
{
inv[1]=1;
for(int i=2;i<=n;++i) inv[i]=(-(p/i)*inv[p%i]%p+p)%p;
fac[0]=ifac[0]=1;
for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%p,ifac[i]=ifac[i-1]*inv[i]%p;
}
inline int fast(int x,int k)
{
if(k<0) return 1;
int ret=1;
while(k)
{
if(k&1) ret=ret*x%p;
x=x*x%p;
k>>=1;
}
return ret;
}
inline int C(int n,int m)
{
if(n<m) return 0;
return fac[n]*ifac[m]%p*ifac[n-m]%p;
}
inline int S(int n,int m)
{
if(n<m) return 0;
int ret=0;
for(int tmp,i=0;i<=m;++i)
{
tmp=fast(m-i,n)*ifac[i]%p*ifac[m-i]%p;
if(i&1) tmp=-tmp;
ret=(ret+tmp+p)%p;
}
return ret;
}
inline void main()
{
n=read(),k=read();
init(k);
for(int i=1;i<=n;++i) sum=(sum+read())%p;
ans=(S(n,k)+(n-1)*S(n-1,k))%p;
printf("%lld
",ans*sum%p);
}
}
signed main()
{
red::main();
return 0;
}