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

    题目描述

    一个有N个元素的集合有2^N个不同子集(包含空集),现在要

    在这2^N个集合中取出若干集合(至少一个),使得它们的交集

    的元素个数为K,求取法的方案数,答案模1000000007。(是质数喔~)

    输入格式

    一行两个整数N,K

    输出格式

    一行为答案。

    样例

    样例输入

     3 2

    样例输出

     6

    数据范围与提示

    样例说明

    假设原集合为{A,B,C}

    则满足条件的方案为:{AB,ABC},{AC,ABC},{BC,ABC},{AB},{AC},{BC}

    数据说明

    对于100%的数据,1≤N≤1000000;0≤K≤N;

    这题是个容斥好题

    然而我蒟蒻的只能怂题解。。。。。

    **********************************************

    首先可以发现单纯的求满足条件的个数是不行的

    可以先将K个元素提前取出

    即C(n,k)*2^(2^n-k)-1为大于k个符合时的方案数

    然而这会把k+1,k+2.。。。情况算是上

    开始蒟蒻想用>=k的情况减>=k+1的情况

    然而这是不行的

    设f[k]=C(n,k)*(2^(2^n-k)-1)

    在算情况k+1时假设固定k个他会由k的状态中C(k+1,k)方式算出

    则-C(K+1,k)*f[k-1]

    然而这样还是会多减

    so还要在k+2加上

    然后就愉快的容斥了.

    if((i-k)&1==0)ans=(ans+f[i-k]*c(k,i))%p;

    else ans=(ans-f[i-k]*c(k,i))%p;

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #define MAXN 1000601
     7 #define ll long long
     8 using namespace std;
     9 ll p=1000000007;
    10 ll f[MAXN];ll sum[MAXN];
    11 ll ni[MAXN];
    12 ll N,K;
    13 ll ci[MAXN];
    14 void kxx()
    15 {
    16    ci[0]=1;
    17    for(int i=1;i<=N;++i)
    18    {
    19       ci[i]=(ci[i-1]<<1)%(p-1);
    20    }
    21 }
    22 ll pow(ll x,ll y)
    23 {
    24     ll ans=1;
    25     while(y>0)
    26     { 
    27         if(y&1)ans=ans*x%p;
    28         x=x*x%p;
    29         y>>=1;
    30     }
    31     return ans%p;
    32 }
    33 ll C(ll x,ll y)
    34 {
    35     if(y>x)return 0;
    36     //printf("ni=%lld
    ",ni[x-y]);
    37     return (sum[x]*ni[y])%p*ni[x-y]%p;
    38 }
    39 void work()
    40 {
    41     for(ll i=K;i<=N;++i)
    42     {
    43         f[i]=C(N,i)*(pow(2ll,ci[N-i])-1ll);
    44         f[i]%=p;
    45     }
    46     ll ans=0;
    47     for(ll i=K;i<=N;++i)
    48     {
    49        if((i-K)%2==0)
    50        {
    51             ans=(ans+C(i,K)*f[i])%p;
    52        }
    53        else
    54             ans=(ans-C(i,K)*f[i]+p)%p;
    55     }
    56     printf("%lld
    ",(ans+p)%p);
    57 }
    58 int b[MAXN];
    59 int main()
    60 {
    61    scanf("%lld%lld",&N,&K);
    62    sum[0]=1;ni[0]=1;sum[1]=1;ni[1]=1;
    63    b[0]=1;b[1]=1;
    64    kxx();
    65    for(ll i=2;i<=N;++i)
    66    { 
    67        sum[i]=(sum[i-1]*i)%p;
    68        b[i]=(p-p/i)*b[p%i]%p;
    69        ni[i]=ni[i-1]*b[i]%p;
    70    }
    71    work();
    72 }
    View Code

     

  • 相关阅读:
    HDU-1205
    HDU-2033
    HDU-2032
    HDU-2031
    HDU-2030
    HDU-2029
    HDU-2028
    HDU-2027
    HDU-2026
    HDU-2025
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11131695.html
Copyright © 2011-2022 走看看