• [BZOJ2839]集合计数


    集合计数

    题目描述

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

    咱也不知道为啥BZOJ上这题长这样

    我是一个分不清交并集的人,对不起数学老师,如有错误,欢迎指正

    基本思路

    依旧一道数论题,组合数学,既然交集要定k,那最先想到的肯定是$C_n^k$,把它摆在这,显然不对,既然交集已经定下来了,我们就需要考虑用谁跟这些交集并,组成集合,交集定好为k了,那么就必须保证跟交集拼的这部分元素一定没有交集,然后的然后咱也不知道大佬们怎么就想到了容斥这个神奇的东西,对,这题需要容斥

    要求剩下的为空集那肿么斥呢,都告诉你容斥了,那就好想了,其实

    $varnothing$=随便选的方法数-交集>=1的方法数+交集>=2的方案数……以此类推

    这样的话最终答案就是$C_n^k*varnothing$的方案数

    接下来就是解决这个交集数>=i的方案数怎么求,我们用f[i]表示交集>=i的方案数,还是先定下$C_n^i$,但是此时并不需要剩下的一定为空集,那剩下的集合就随便拼就好了,那方案数就是$2^{2^{n-i}}$(就是2的2的n-i次幂,自己应该可以想到,就是先拼成集合,再把集合拼成集合),但是要注意这么拼出来可能会是空集拼上空集,这显然不符合题意,所以要-1,故最终

    $f[i]=C_n^i*(2^{2^{n-i}}-1)$

    关于一加一减那一块,你可以选择直接判i的奇偶或者加一个(-1)i就好了

    提问:在求f[i]中的n是输入的n吗?我大概在这死了一节多课

    答:并不是

    思考一下,你拼空集的时候还剩下n个元素吗?显然不是,因为你前面已经定下了k个元素作为交集,那此时再选元素,显然不能同一个元素选两次,所以现在的n实际上应该是n-k

    到此这题就搞出来了,然后就来讲讲我都WA过些啥

    WA70

    是我高看了取模这种东西,要知道取模之后不一定严格遵守取模之前的大小关系,所以就会出现全集的方案数小于后面某一的个方案数,这样的话,ans就会出负数了,然后磕了一节课,最后的解决方案是如果答案为负,加一个模数就好了

    WA90

    我更像个zz了,我数组开的1000000,然后就WA了

    几点注意

    关于那个$2^{2^{n-i}}$的求法,给$2^{n-i}$取模肯定就死翘翘了,不取模数据大了依旧死翘翘,那怎么解决呢?换个不影响结果的模数,这个时候就用到我不会的玩意了

    图片截取自不认识的大佬博客我不会直接加链接,我现在学会了,已经加过去了

    而我依旧zz,1000000007的欧拉函数怎么求?他是个质数,是个质数,那他的欧拉函数就是1000000006!!!!!!!!

    long long记得开,求逆元可以用线性的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #define ll long long
     5 #define maxn 1000100
     6 const long long mod1=1000000007;
     7 const long long mod2=1000000006;
     8 using namespace std;
     9 int n,k;
    10 ll ny[maxn],jc[maxn],f[maxn];
    11 ll ksm(ll a,ll b,ll c)
    12 {
    13     ll ans=1;
    14     a=a%c;
    15     while(b>0)
    16     {
    17         if(b&1)  ans=(ans*a)%c;
    18         b=b>>1;
    19         a=(a*a)%c;
    20     }
    21     return ans%c;
    22 }
    23 ll c(int n,int m)
    24 {
    25     if(n<m)  return 0;
    26     if(n<mod1&&m<mod1)  return ((jc[n]*ny[m])%mod1*ny[n-m])%mod1;
    27     return (c(n/mod1,m/mod1)*c(n%mod1,m%mod1))%mod1;
    28 }
    29 int main()
    30 {
    31     //freopen("3.in","r",stdin);
    32     //freopen("WA.out","w",stdout);
    33     scanf("%d%d",&n,&k);
    34     jc[0]=1;
    35     for(int i=1;i<=n;++i)  jc[i]=(jc[i-1]*i)%mod1;
    36     ny[n]=ksm(jc[n],mod1-2,mod1);
    37     for(int i=n;i>=1;--i)  ny[i-1]=(ny[i]*i)%mod1;
    38     int ls=n-k;
    39     for(int i=0;i<=ls;++i)
    40     {
    41         ll mi=ksm(2,ls-i,mod2);
    42         ll ch;
    43         if(i&1)  ch=-1;
    44         else  ch=1;
    45         f[i]=(c(ls,i)*(ksm(2,mi,mod1)-1))%mod1;
    46         f[i]*=ch;
    47     }
    48     ll tot=0;
    49     for(int i=0;i<=ls;++i)
    50     {
    51         tot+=f[i];
    52         tot=tot%mod1;
    53     }
    54     ll ans=(c(n,k)*tot)%mod1;
    55     while(ans<0)  ans+=mod1;
    56     printf("%lld
    ",ans);
    57     return 0;
    58 }
  • 相关阅读:
    转载:SuperMap 网络带宽对B/S项目的影响有多大?如何计算所需要的带宽?
    转载:使用JWT做用户登陆token校验
    转载:互联网在线地图平台对比分析
    jmeter计时器讲解
    ReactNative setNativeProps
    关于xxx.h file not found 的问题
    注册推送通知
    ios ViewController present不同的方向
    ReactNative常见报错
    ios 后台模式
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11137556.html
Copyright © 2020-2023  润新知