[CF961G] Partitions [第二類斯特林數]

Link
https://www.luogu.org/problemnew/show/CF961G


V(R)=SRW(S)=SRSxSwxV(R)=\sum\limits_{S\in R}W(S)=\sum\limits_{S\in R}|S|\sum\limits_{x\in S}w_x
考慮換一下,計數每個數產生貢獻的次數?
不難發現應該是 s=1n(n1s1)\{nsk1\}s\sum\limits_{s=1}^n{n-1\choose s-1}{n-s\brace k-1}s
V(R)=V(R)= 上面那個東西乘上 x=1nwx\sum\limits_{x=1}^nw_x


然後怎麼做呢?斯特林數那一部分不好直接搞吧,那就弄開
推一下斯特林通項?
我們知道 \{nk\}{n\brace k} 如果沒有那個集合非空的限制而且集合有序就是等於 nkn^k
但是現在有非空的限制。我們考慮容斥:
nn 個有序元素劃分爲 kk 個有序集合,限制至少 ii 個集合是空噠,方案數 (ki)(ki)n{k\choose i}(k-i)^n
容斥:\{nk\}=1k!i=0k(1)i(ki)(ki)n{n\brace k}=\frac{1}{k!}\sum\limits_{i=0}^k(-1)^i{k\choose i}(k-i)^n 。外面乘上的 1k!\frac{1}{k!} 使集合無序。


最後那個就先不管了,我們暫時只考慮前面的係數 PP
P=s=1n(n1s1)s(k1)!i=0k1(1)i(k1i)(ki1)ns=s=1n(n1s1)si=0k1(1)i(ki1)nsi!(ki1)!=i=0k1(1)ii!(ki1)!s=1ns(n1s1)(ki1)ns\begin{array}{rcl} P&=&\sum\limits_{s=1}^n{n-1\choose s-1}\cdot\frac{s}{(k-1)!}\sum\limits_{i=0}^{k-1}(-1)^i{k-1\choose i}(k-i-1)^{n-s}\\ &=&\sum\limits_{s=1}^n{n-1\choose s-1}s\cdot\sum\limits_{i=0}^{k-1}\frac{(-1)^i(k-i-1)^{n-s}}{i!(k-i-1)!}\\ &=&\sum\limits_{i=0}^{k-1}\frac{(-1)^i}{i!(k-i-1)!}\sum\limits_{s=1}^ns{n-1\choose s-1}(k-i-1)^{n-s} \end{array}
前面那個好弄了
搞後面那個 湊係數 湊組合恆等(挪走 ss ) 湊二項式
Q=s=1ns(n1s1)(ki1)ns=s=1n(n1s1)(s1)(ki1)ns+s=1n(n1s1)(ki1)ns=(n1)s=2n(n2s2)(ki1)ns+s=0n1(n1s)(ki1)n1s=(n1)s=0n2(n2s)(ki1)n2s+(ki)n1=(n1)(ki)n2+(ki)n1\begin{array}{rcl} Q&=&\sum\limits_{s=1}^ns{n-1\choose s-1}(k-i-1)^{n-s}\\ &=&\sum\limits_{s=1}^n{n-1\choose s-1}(s-1)(k-i-1)^{n-s}+\sum\limits_{s=1}^n{n-1\choose s-1}(k-i-1)^{n-s}\\ &=&(n-1)\sum\limits_{s=2}^n{n-2\choose s-2}(k-i-1)^{n-s}+\sum\limits_{s=0}^{n-1}{n-1\choose s}(k-i-1)^{n-1-s}\\ &=&(n-1)\sum\limits_{s=0}^{n-2}{n-2\choose s}(k-i-1)^{n-2-s}+(k-i)^{n-1}\\ &=&(n-1)(k-i)^{n-2}+(k-i)^{n-1}\\ \end{array}

P=i=0k1(1)i(ki)n2(k+ni1)i!(ki1)!P=\sum\limits_{i=0}^{k-1}\frac{(-1)^i(k-i)^{n-2}(k+n-i-1)}{i!(k-i-1)!}


另一種思路是考慮統計每一個數對某個數的貢獻
P=\{nk\}+(n1)\{n1k\}P={n\brace k}+(n-1){n-1\brace k}
也一樣。


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
using namespace std;
const long long p = 1e9+7;
const int MAXN = 2e5+5;
int n, k;
long long ans, sum;
long long stair[MAXN];
inline long long qpow(long long a, long long b)
{
	if (b < 0) return 1;
    register long long ret = 1;
    while (b)
    {
        if (b & 1)
        {
            ret *= a;
            ret %= p;
        }
        a *= a;
        a %= p;
        b >>= 1;
    }
    return ret;
}
inline void Adjust(long long& x)
{
    x = (x % p) + p;
    if (x >= p) x -= p;
}
int main()
{
    scanf("%d%d", &n, &k);
    for (register int t, i = 1; i <= n; ++i)
    {
        scanf("%d", &t);
        sum += t;
        if (sum >= p) sum -= p;
    }
    stair[0] = 1;
    for (register int i = 1; i <= k; ++i)
    {
        stair[i] = stair[i-1] * i % p;
    }
    for (register int i = 0; i < k; ++i)
    {
    	if (i & 1) ans -= qpow(k-i,n-2) * (k+n-i-1) % p * qpow(stair[i]*stair[k-i-1]%p, p-2) % p, Adjust(ans);
    	else ans += qpow(k-i,n-2) * (k+n-i-1) % p * qpow(stair[i]*stair[k-i-1]%p, p-2) % p, ans %= p;
    }
    printf("%I64d", ans * sum % p);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章