zoukankan      html  css  js  c++  java
  • 【BZOJ2839】集合计数 组合数+容斥

    【BZOJ2839】集合计数

    Description

    一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得它们的交集的元素个数为K,求取法的方案数,答案模1000000007。(是质数喔~)

    Input

    一行两个整数N,K

    Output

    一行为答案。

    Sample Input

    3 2

    Sample Output

    6

    HINT

    【样例说明】
    假设原集合为{A,B,C}
    则满足条件的方案为:{AB,ABC},{AC,ABC},{BC,ABC},{AB},{AC},{BC}
    【数据说明】
         对于100%的数据,1≤N≤1000000;0≤K≤N;

    题解:容斥,考虑选出若干集合使得交集至少为k的方案数,有$f(i)=C _n^i imes (2^{2^{n-i}}-1)$,可以理解为已经选定了i个,剩下$2^{n-i}$个集合,每个可以选或不选,但是不能一个也不选。但是这样做肯定会有重复的,我们思考容斥系数是什么。

    当我们计算交集至少为k的时候,每个交集为j的方案都会被计算$C_j^k$次,所以
    f(k)的系数是1
    f(k+1)的系数是$-C_{k+1}^k$
    f(k+2)的系数$-C_{k+2}^k+C_{k+1}^kC_{k+2}^{k+1}=C_{k+2}^k$(小tips:$C_N^MC_M^S=C_N^SC_{N-S}^{N-M}$)

    以此类推,f(i)的系数就是$(-1)^{i-k}C_i^k$。

    所以答案为$sumlimits_{i=k}^n(-1)^{i-k}C_i^kC_n^i(2^{2^{n-i}}-1)$

    求组合数需要线性筛逆元,方法:$i^{-1}equiv -lfloor{pover i} floor imes(p\%i)^{-1}(mod p)$

    求$(2^{2^i}-1)$可以采用从n到k枚举i的方法,初值tmp=1,然后tmp=tmp*(tmp+2)。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const ll mod=1000000007;
    ll n,k,ans;
    ll ine[1000010],jcc[1000010],jc[1000010];
    ll c(ll x,ll y)
    {
    	return jc[x]*jcc[y]%mod*jcc[x-y]%mod;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&k);
    	ll i,j,flag,tmp;
    	ine[1]=jc[1]=jcc[1]=jc[0]=jcc[0]=1;
    	for(i=2;i<=n;i++)
    	{
    		ine[i]=(mod-(mod/i)*ine[mod%i])%mod;
    		jcc[i]=jcc[i-1]*ine[i]%mod;
    		jc[i]=jc[i-1]*i%mod;
    	}
    	for(i=n,flag=((n-k)&1)?-1:1,tmp=1;i>=k;i--)
    	{
    		ans=(ans+mod+flag*c(i,k)*c(n,i)%mod*tmp%mod)%mod;
    		flag=-flag,tmp=tmp*(tmp+2)%mod;
    	}
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    物流与仓库
    测试使用
    禅修的升级
    《引爆点 马尔科姆 格拉德威尔》读书笔记总结----《创业必读书第20本》--创业第三关做好业务:3,如何做好营销和增长第4本
    shell
    Vue中常用的方法记录
    前端工程化3-tapable
    Browser上传文件到华为云/七牛云 详细步骤
    immutable
    shell利用叮叮发送消息
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7124411.html
Copyright © 2011-2022 走看看