• bzoj 2839 集合计数


    n 个元素,选出若干子集使得交集大小为 k,求不同选择方案数

    $n,k leq 10^6$

    sol:

    首先,先选 k 个元素为交集,这一步是 $C_{n}^{k}$

    剩下就是选择一些没有交集的集合方案数

    考虑容斥,交集为 $emptyset$ 的方案数 = 随便选的方案数 - 交集大于等于 1 的方案数 + 交集大于等于 2 的方案数 ...

    然后考虑求交集大于等于 i 的方案数

    跟上面一样,先选出来 i 个,剩下的元素的集合任意选,选出来是 $C_{n}^i imes (2 ^ {2 ^ {(n - i)}} - 1)$ 种,然后原式就是

    $sum_{i=0}^n (-1)^i imes C_{n}^i imes (2 ^ {2 ^ {(n - i)}} - 1)$

    求一下就可以了

    听说叫做二项式反演

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int mod = 1000000007,maxn = 1000000 + 50;
    int n,k;
    int fac[maxn],ifac[maxn];
    inline int ksm(int x,int t)
    {
        int res = 1;
        while(t)
        {
            if(t & 1)res = 1LL * res * x % mod;
            x = 1LL * x * x % mod;
            t = t >> 1;
        }return res;
    }
    inline int C(int n,int m)
    {
        if(n < 0 || m < 0 || n < m)return 0;
        return (((1LL * ifac[m] * ifac[n - m]) % mod) * fac[n]) % mod;
    }
    int main()
    {
        n = read(),k = read();
        fac[0] = 1;for(int i=1;i<=n;i++)fac[i] = (1LL * fac[i - 1] * i) % mod;
        ifac[n] = ksm(fac[n],mod - 2);for(int i=n-1;~i;i--)ifac[i] = (1LL * ifac[i + 1] * (i + 1)) % mod;
        LL ans = 0,now = 2;n -= k;
        for(int i=n;~i;i--)
        {
            (ans += ((i & 1) ? -1 : 1) * C(n,i) * (now - 1) % mod) %= mod;
            (now *= now) %= mod;
        }n += k;(ans *= C(n,k)) %= mod;
        ans = (ans + mod) % mod;
        cout<<ans<<endl;
    }
    View Code

    upd:formal 的学了一下二项式反演

    如果有 $f(n) = sumlimits_{i=1}^nC_n^i g(i)$ ,则有 $g(n) = sumlimits_{i=1}^n (-1)^{(n-i)} imes C_n^i f(i)$

  • 相关阅读:
    国内顺利使用Google的另类技巧
    Java进程间通信
    Java 多线程(七) 线程间的通信——wait及notify方法
    转:关于copy_to_user()和copy_from_user()的一些用法
    转: pthread_detach()函数
    转:pthread_create()
    转: ubuntu配置NFS,挂载开发板
    转:全志A20 GPIO 总结文档
    转:Linux 内核中的 cdev_alloc和cdev_add
    转:1.1 cdev_init cdev_alloc 使用说明
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10231420.html
Copyright © 2020-2023  润新知