bzoj2839 关于组合数的若干yy

考虑容斥,最后的答案为 ni=k(1)ikCinCki(22ni1)
实际上-1和最后一部分并不需要解释,然后我们看看如何证明这个的正确性。


辣鸡的证明

关于普通的容斥原理,我们可以用二项式定理yy
当我们发现对于每一个交集大小为n的选法,他最后被统计的次数是这个.
ni=k(1)ikCinCki 由于我菜,就上uoj群问了一发,钊神说这似乎是证明二项式反演的啥啥玩意儿orz.
我们根据组合数的公式,有
CinCki=CknCiknk

那么
ni=k(1)ikCinCki=0  (k<n)
= ni=k(1)ikCknCiknk=0  (k<n)
= Cknni=k(1)ikCiknk=0  (k<n)
= Ckn(11)nk
考虑这个式子,当n>k的时候,他=0,当n=k时,他=1.这就说明我们最后只算了交集为k的情况.


丑陋的代码

#include<cstdio>
#include<algorithm>

const int P = 1e9 + 7, N = 1e6 + 8;

int n, k;

typedef long long ll;

ll la = 2, res, jc[N], jc_rev[N];

ll C (int n, int m) {
    if (m > n) return 0;
    return jc[n] * jc_rev[m] % P * jc_rev[n - m] % P;
}

ll quick_power (ll A, int B) {
    ll C = 1;
    for (; B; B >>= 1, A = A * A % P) if (B & 1) C = C * A % P;
    return C;
}

int main () {
    scanf ("%d%d", &n, &k);
    jc[0] = 1; for (int i = 1; i <= n; ++i) jc[i] = jc[i - 1] * i % P;
    jc_rev[n] = quick_power (jc[n], P - 2);
    for (int i = n - 1; ~i; --i) jc_rev[i] = jc_rev[i + 1] * (i + 1) % P;
    for (int i = n, fu = 1; i >= k; --i, fu = -fu, la = la * la % P) { 
        res = ((la - 1) * C (i, k) % P * C (n, i) - res) % P;
    }
    printf ("%lld\n", (res + P) % P);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值