zoukankan      html  css  js  c++  java
  • BZOJ2839集合计数

    题目描述

    一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得
    它们的交集的元素个数为K,求取法的方案数,答案模1000000007。(是质数喔~)
    题解
    假设我们已经确定了这k个元素都是谁,最后再乘上C(n,k)就可以了。
    根据容斥原理(二项式反演)可知,答案为选出至少k个的方案数-选出至少k+1个的方案数+选出至少k+2个的方案数。。。
    如何求选出至少x个的方案数,考虑有多少种集合包含x个元素,答案是2n-x(相当于我们已经确定了x个元素)。
    他们中每个集合都可以选或不选,但是不能都不选。
    所以是2r-1,r是刚才那个2n-x
    最后因为我们固定了k个,有x-k个没有固定,再乘上C(n-k,x-k)
    注意指数要%mod-1
    代码
    #include<iostream>
    #include<cstdio>
    #define N 1000009
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    ll inv[N],jie[N],ni[N],n,k,ans;
    inline ll power(ll x,ll y){
        ll ans=1;
        while(y){
            if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;
        }
        return ans;
    }
    inline ll C(int n,int m){
        return jie[n]*ni[m]%mod*ni[n-m]%mod;
    }
    int main(){
        cin>>n>>k;
        inv[0]=1;
        for(int i=1;i<=n;++i)inv[i]=inv[i-1]*2%(mod-1);
        jie[0]=1;
        for(int i=1;i<=n;++i)jie[i]=jie[i-1]*i%mod;ni[n]=power(jie[n],mod-2);
        for(int i=n-1;i>=0;--i)ni[i]=ni[i+1]*(i+1)%mod;
        for(int i=k;i<=n;++i){
             if((i-k)&1)ans-=C(n-k,i-k)*(power(2,inv[n-i])-1)%mod;
             else ans+=C(n-k,i-k)*(power(2,inv[n-i])-1)%mod;
             ans=(ans%mod+mod)%mod;
        }
        ans=ans*C(n,k)%mod;
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Mybatis基本用法--下
    Mybatis基本用法--中
    Mybatis基本用法--上
    Java规范推荐
    jquery、js获取页面高度宽度等
    linux ssh -l 命令运用
    div的onblur事件
    js获取url中的参数方法
    div内部元素居中
    oracle排序
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10278257.html
Copyright © 2011-2022 走看看