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

    问题 J: 集合计数
    时间限制: 1 Sec 内存限制: 128 MB
    题目描述
    一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得
    它们的交集的元素个数为K,求取法的方案数,答案模1000000007。(是质数喔~)
    输入
    一行两个整数N,K
    输出
    一行为答案。
    样例输入
    3 2
    样例输出
    6

    如果固定k个元素必须选,则还剩下2^(n-k)个集合,
    因此,交集>=k的方案数就是f[k]=C(n,k)*2^(2^(n-k))
    很明显我们要去重,那就要用到容斥原理了。
    ans=f[k]* C(k,k)-f[k+1]* C(k+1,k)+f[k+2] *C(k+2,k)…..
    也就是说当有k+1个交集时,得讨论一下是哪几个重了。

    #include <cstdio>
    #define p 1000000007
    #define N 1000000
    #define ll long long
    int n,k;ll ans,a[N+5],b[N+5],xp[N+5];
    ll cheng(ll x,ll m)
    {
         ll ans=1;
         for(;m;m>>=1,x=x*x%p)if(m&1)ans=ans*x%p;
         return ans;
    }
    ll C(int n,int m){return (a[n]*b[m]%p)*b[n-m]%p;}
    void init()
    {
        a[0]=b[0]=xp[0]=1;
        for(ll i=1;i<=n;i++)a[i]=a[i-1]*i%p;
        for(int i=1;i<=n-k;i++)xp[i]=xp[i-1]*2ll%(p-1);
        b[n]=cheng(a[n],p-2);
        for(ll i=n-1;i>=1;i--)b[i]=b[i+1]*(i+1)%p;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        init();
        for(ll i=k,f=1;i<=n;i++,f=-f)
            ans=(ans+f*C(i,k)*cheng(2,xp[n-i])%p*C(n,i)%p+p)%p;
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    maven常用命令
    div标签width:auto无效
    将本地文件推送到码云
    Spring事件监听讲解
    常用js代码积累
    HTML中块级元素和行内元素的总结和区分
    box-shadow详解
    设置最小宽高的作用
    Java英语词汇表
    标识符
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7679028.html
Copyright © 2011-2022 走看看