CF961G Partitions(第二類斯特林數)

題目

CF961Ghtml

前置

斯特林數\(\Longrightarrow\)斯特林數及反演總結spa

作法

相信你們能得出一個一眼式:\[Ans=\sum\limits_{i=1}^n w_i\sum\limits_{s=1}^n s\cdot C_{n-1}^{s-1}\begin{Bmatrix}k-1\\n-s\end{Bmatrix}\]code

而後就開始推式:
\[\begin{aligned}\\ Sum&=\sum\limits_{s=1}^n s\cdot C_{n-1}^{s-1}\begin{Bmatrix}n-s\\k-1\end{Bmatrix}\\ &=\sum\limits_{s=1}^n s\cdot C_{n-1}^{s-1}\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!}\frac{(k-i-1)^{n-2}}{(k-i-1)!}\\\ &=\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}\sum\limits_{s=1}^n s\cdot C_{n-1}^{s-1}(k-i-1)^{n-s}\\ &=\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}(\sum\limits_{s=1}^nC_{n-1}^{s-1}(k-i-1)^{n-s}+\sum\limits_{s=1}^n (s-1)C_{n-1}^{s-1}(k-i-1)^{n-s})\\ &=\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}(\sum\limits_{s=1}^nC_{n-1}^{s-1}(k-i-1)^{n-s}+(n-1)\sum\limits_{s=1}^n C_{n-2}^{s-2}(k-i-1)^{n-s})\\ &=\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}((k-i)^{n-1}+(n-1)(k-i)^{n-2})\\ &=\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}(k-i)^{n-2}(k-i+n-1)\\ \end{aligned}\]htm

然而。。。這。。。比賽的時候能推出這麼一大堆式子的**是神仙吧blog

因而有種更簡單的方法:\(|S|\sum w_i\)
咱們能夠理解爲:劃分好集合後,每一個點都對當前點有\(w_i\)的貢獻get

本身對本身的貢獻顯然就是\(\begin{Bmatrix}n\\k\end{Bmatrix}\)
其餘點對自己的貢獻就是先分好\(k\)個集合,再放進去,\((n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix}\)it

\[Ans=\sum\limits_{i=1}^nw_i(\begin{Bmatrix}n\\k\end{Bmatrix}+(n-1)\begin{Bmatrix}n-1\\k\end{Bmatrix})\]io

Code

有關斯特林數及反演的更多姿式\(\Longrightarrow\)點這裏class

#include<cstdio>
typedef int LL;
const LL mod=1e9+7,maxn=2e5+9;
inline LL Read(){
    LL x(0),f(1); char c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<3)+(x<<1)+c-'0'; c=getchar();
    }
    return x*f;
}
inline LL Pow(LL base,LL b){
    LL ret(1);
    while(b){
        if(b&1) ret=1ll*ret*base%mod; base=1ll*base*base%mod; b>>=1;
    }return ret;
}
LL fav[maxn],fac[maxn];
inline LL Get(LL n,LL m){
    LL ret(0);
    for(LL i=0;i<=m;++i)
        ret=1ll*(ret+1ll*(i&1?mod-1:1)*fav[i]%mod*Pow(m-i,n)%mod*fav[m-i]%mod)%mod;
    return ret;
}
LL n,sum,k;
LL w[maxn];
int main(){
    n=Read(); k=Read();
    for(LL i=1;i<=n;++i){
        w[i]=Read();
        (sum+=w[i])%=mod;
    }
    fac[0]=fac[1]=1;
    for(LL i=2;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
    fav[n]=Pow(fac[n],mod-2);
    for(LL i=n;i>=1;--i) fav[i-1]=1ll*fav[i]*i%mod;
    printf("%d\n",1ll*sum*((1ll*Get(n,k)%mod+1ll*(n-1)*Get(n-1,k)%mod)%mod)%mod);
    return 0;
}
相關文章
相關標籤/搜索