[CF961G] Partitions [第二类斯特林数]

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


V ( R ) = ∑ S ∈ R W ( S ) = ∑ S ∈ R ∣ S ∣ ∑ x ∈ S w x V(R)=\sum\limits_{S\in R}W(S)=\sum\limits_{S\in R}|S|\sum\limits_{x\in S}w_x V(R)=SRW(S)=SRSxSwx
考虑换一下,计数每个数产生贡献的次数?
不难发现应该是 ∑ s = 1 n ( n − 1 s − 1 ) \{ n − s k − 1 \} s \sum\limits_{s=1}^n{n-1\choose s-1}{n-s\brace k-1}s s=1n(s1n1){k1ns}s
V ( R ) = V(R)= V(R)= 上面那个东西乘上 ∑ x = 1 n w x \sum\limits_{x=1}^nw_x x=1nwx


然后怎么做呢?斯特林数那一部分不好直接搞吧,那就弄开
推一下斯特林通项?
我们知道 \{ n k \} {n\brace k} {kn} 如果没有那个集合非空的限制而且集合有序就是等于 n k n^k nk
但是现在有非空的限制。我们考虑容斥:
n n n 个有序元素划分为 k k k 个有序集合,限制至少 i i i 个集合是空哒,方案数 ( k i ) ( k − i ) n {k\choose i}(k-i)^n (ik)(ki)n
容斥: \{ n k \} = 1 k ! ∑ i = 0 k ( − 1 ) i ( k i ) ( k − i ) n {n\brace k}=\frac{1}{k!}\sum\limits_{i=0}^k(-1)^i{k\choose i}(k-i)^n {kn}=k!1i=0k(1)i(ik)(ki)n 。外面乘上的 1 k ! \frac{1}{k!} k!1 使集合无序。


最后那个就先不管了,我们暂时只考虑前面的系数 P P P
P = ∑ s = 1 n ( n − 1 s − 1 ) ⋅ s ( k − 1 ) ! ∑ i = 0 k − 1 ( − 1 ) i ( k − 1 i ) ( k − i − 1 ) n − s = ∑ s = 1 n ( n − 1 s − 1 ) s ⋅ ∑ i = 0 k − 1 ( − 1 ) i ( k − i − 1 ) n − s i ! ( k − i − 1 ) ! = ∑ i = 0 k − 1 ( − 1 ) i i ! ( k − i − 1 ) ! ∑ s = 1 n s ( n − 1 s − 1 ) ( k − i − 1 ) n − s \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} P===s=1n(s1n1)(k1)!si=0k1(1)i(ik1)(ki1)nss=1n(s1n1)si=0k1i!(ki1)!(1)i(ki1)nsi=0k1i!(ki1)!(1)is=1ns(s1n1)(ki1)ns
前面那个好弄了
搞后面那个 凑系数 凑组合恒等(挪走 s s s ) 凑二项式
Q = ∑ s = 1 n s ( n − 1 s − 1 ) ( k − i − 1 ) n − s = ∑ s = 1 n ( n − 1 s − 1 ) ( s − 1 ) ( k − i − 1 ) n − s + ∑ s = 1 n ( n − 1 s − 1 ) ( k − i − 1 ) n − s = ( n − 1 ) ∑ s = 2 n ( n − 2 s − 2 ) ( k − i − 1 ) n − s + ∑ s = 0 n − 1 ( n − 1 s ) ( k − i − 1 ) n − 1 − s = ( n − 1 ) ∑ s = 0 n − 2 ( n − 2 s ) ( k − i − 1 ) n − 2 − s + ( k − i ) n − 1 = ( n − 1 ) ( k − i ) n − 2 + ( k − i ) n − 1 \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} Q=====s=1ns(s1n1)(ki1)nss=1n(s1n1)(s1)(ki1)ns+s=1n(s1n1)(ki1)ns(n1)s=2n(s2n2)(ki1)ns+s=0n1(sn1)(ki1)n1s(n1)s=0n2(sn2)(ki1)n2s+(ki)n1(n1)(ki)n2+(ki)n1

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


另一种思路是考虑统计每一个数对某个数的贡献
P = \{ n k \} + ( n − 1 ) \{ n − 1 k \} P={n\brace k}+(n-1){n-1\brace k} P={kn}+(n1){kn1}
也一样。


#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值