• BZOJ 2339: [HNOI2011]卡农 DP+容斥原理


    题意:在 $n$ 个数的 $2^n-1$ 个非空子集中选取 $m$ 个,且必须满足:  

    1. $m$ 个子集两两不同.

    2. 每个数在 $m$ 个子集中出现总次数为偶数.   

    3. 每个子集非空.       

    令 $f[i]$ 表示选出了 $i$ 个集合且满足了上述 3 条限制的方案数.        

    直接求 $f[i]$ 比较困难,考虑容斥:    

    如果前 $i-1$ 个集合确定,那么集合 $i$ 也唯一确定 (即前 $i-1$ 个中出现奇数次的数).     

    总:$A_{2^n-1}^{i-1}$.     

    有 2 种情况不合法:1. 集合 $i$ 为空集 2. 与前面的一个集合相同.   

    集合 $i$ 为空集,意味着前 $i-1$ 个集合中没有出现次数为奇数的数字,即 $f[i-1].$  

    集合 $i$ 与一个集合 $j$ 相同,意味着除去集合 $i,j$ 之外的集合是合法的,即 $f[i-2].$     

    而 $i$ 集合有 $2^n-1-(i-2)$ 种选取方式,所以这部分不合法的方案数是:$[2^n-1-(i-2)] imes f[i-2] imes (i-1)$.       

    由于上述推导过程中默认集合是有序的,所以答案还要除一个 $m!$.

    #include <bits/stdc++.h>  
    #define N 1000007 
    #define ll long long 
    #define mod 100000007 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;
    int qpow(int x,int y) 
    {
        int tmp=1; 
        for(;y;y>>=1,x=(ll)x*x%mod) 
            if(y&1) tmp=(ll)tmp*x%mod; 
        return tmp; 
    }
    int A[N],f[N];  
    int main()
    { 
        // setIO("input");  
        int i,j,n,m,inv; 
        scanf("%d%d",&n,&m);   
        inv=A[0]=1;   
        for(i=2;i<=m;++i) inv=(ll)i*inv%mod;   
        inv=qpow(inv,mod-2);   
        int mx=(qpow(2,n)-1+mod)%mod;     
        for(i=1;i<=m;++i) 
            A[i]=(ll)A[i-1]*(mx-i+1+mod)%mod;    
        f[0]=1,f[1]=0;   
        for(i=2;i<=m;++i) 
        {
            f[i]=(ll)(A[i-1]-f[i-1]+mod)%mod;  
            f[i]=(ll)(f[i]-(ll)f[i-2]*(i-1)%mod*(qpow(2,n)-1-(i-2)+mod)%mod+mod)%mod;  
        }
        printf("%d
    ",(ll)f[m]*inv%mod);   
        return 0;
    }
    

      

  • 相关阅读:
    myeclipse16怎么去掉项目中的CodeLive Panel?
    JTable动态刷新数据
    javaEE中config.properties文件乱码解决办法
    ZipUtil
    uri中为什么本地文件file后面跟三个斜杠, http等协议跟两个斜杠?
    Java中Access restriction:····的解决方法
    libGDX开发环境搭建-Android Studio 最新版
    mxnet反序列化: 由symbol到gluon
    mxnet symbol reshape用法
    Hybrid
  • 原文地址:https://www.cnblogs.com/guangheli/p/12158938.html
Copyright © 2020-2023  润新知