集合计数

题目描述

一个有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

 

原文地址:https://www.cnblogs.com/Wwb123/p/11131695.html