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

    我想的容斥和题解不太一样

    我也是想先在n个里确定K个

    然后设 $$f_i=C_n^i*sum_{p=0}^{n-i} $$

    $$ ans=f_K-f_{K+1}+f_{K+2}... $$

    然而这个并不对,3 2 的样例 算$f_k$的时候就已经是6了

    正解:

    $$ ans=C_n^K*( C_{n-K}^0*2^{2^{n-K}}-C_{n-K}^1*2^{2^{n-K-1}}... ) $$

    解释:

    先枚举确定n个里面的K个

    在枚举另外 n-K 个元素里有几个是在交集里被选上了

    $2^{2^{i}}$意思是 有i个元素剩余,子集有$2^i$个,在这些子集里再选

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int N=1000006;
    const int mod=1000000007;
    
    int ou(int x)
    {
        int tt=x,q1=sqrt(x);
        for(int i=2;i<=q1;++i)
            if(x%i==0)
            {
                tt=tt-tt/i;
                while(x%i==0)
                    x/=i;
            }
        if(x!=1)
            tt=tt-tt/x;
        return tt;
    }
    
    ll qpow(ll a,int ci,int mm)
    {
        ll ans=1;
        while(ci)
        {
            if(ci&1)
                ans=ans*a%mm;
            a=a*a%mm;
            ci>>=1;
        }
        return ans;
    }
    
    int n,K;
    ll mi[N],mi2[N];
    ll jie[N],jieni[N];
    
    void chu()
    {
        int mod2=ou(mod);
        mi[0]=1;
        for(int i=1;i<=n;++i)
          mi[i]=mi[i-1]*2%mod2;
        for(int i=0;i<=n;++i)
          mi2[i]=qpow(2,mi[i],mod);
        
        jie[0]=1;
        for(int i=1;i<N;++i)
          jie[i]=jie[i-1]*i%mod;
        jieni[N-1]=qpow(jie[N-1],mod-2,mod)%mod;
        for(int i=N-2;i>=1;--i)
          jieni[i]=jieni[i+1]*(i+1)%mod;
        jieni[0]=1;
    }
    
    ll C(int n,int m)
    {
        if( n<0||m<0||n<m )
            return 0;
        return jie[n]*jieni[m]%mod*jieni[n-m]%mod;
    }
    
    ll work()
    {
        ll ans=0,tt;
        int q1=n-K;
        for(int i=0;i<=q1;++i)
        {
            tt=C(n-K,i)*mi2[n-K-i]%mod;
            //printf("i=%d tt=%lld
    ",i,tt);
            if(i&1)
                ans=(ans-tt+mod)%mod;
            else
              ans=(ans+tt)%mod;
        }
        return ans*C(n,K)%mod;
    }
    
    int main(){
        
        scanf("%d%d",&n,&K);
        chu();
        cout<<work();
    }
    AA
  • 相关阅读:
    SDOI2011古代朱文
    LIS 堆优化
    ZR2019 广州 游记
    LG2709 小B的询问
    [SCOI2009] 生日礼物
    [SDOI2008]沙拉公主的困惑
    [LG3396]哈希冲突
    ZROI2018.8.2 菜鸡互啄杯组队 ACM 赛
    ZROI 菜鸡互啄杯 III
    [LG4016] 负载平衡问题
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7675382.html
Copyright © 2011-2022 走看看