zoukankan      html  css  js  c++  java
  • bzoj 2839: 集合计数【容斥原理+组合数学】

    首先,考虑容斥,我们所要的答案是并集至少有( k )个数的方案数减去并集至少有( k+1 )个数的方案数加上并集至少有( k )个数的方案数……
    在n个数中选i个的方案数是( C_{n}^{i} ),n种集合的组合方案数为( 2^n )
    并集至少有i个元素的方案数即为选( i )个元素的方案数( C_{n}^{i} ),乘上剩下( n-i )个元素任意组合的方案数( 2{2{n-i}-1} )
    然后乘上容斥系数( (-1)^{i-k} ),再乘上在并集的( i )个元素中选择( k )个元素的方案数( C_{i}^{k} )
    答案即为:( ans=sum_{i=k}{i<=n}(-1){i-k}*C_{n}{i}*C_{i}{k}*2{2{n-i}-1} ),ans可能为负数,记得最后( ans=(ans\%mod+mod)\%mod )

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const long long mod=1e9+7,N=1000005;
    long long n,k,inv[N],fac[N],ans;
    long long ksm(long long a,long long b)
    {
    	long long r=1ll;
    	while(b)
    	{
    		if(b&1)
    			r=r*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return r;
    }
    long long C(long long n,long long m)
    {
    	return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&k);
    	fac[0]=1;
    	for(long long i=1;i<=n;i++)
    		fac[i]=fac[i-1]*i%mod;//,cout<<fac[i]<<" ";
    	inv[n]=ksm(fac[n],mod-2);
    	for(long long i=n-1;i>=0;i--)
    		inv[i]=inv[i+1]*(i+1)%mod;//,cout<<inv[i]<<endl;;
    	for(long long i=n,b=2;i>=k;i--,b=b*b%mod)
    		ans=(ans+((((i-k)&1)?-1:1)*C(n,i)%mod*C(i,k)%mod*(b+mod-1)%mod))%mod;
    	printf("%lld",(ans%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/lokiii/p/8213459.html
Copyright © 2011-2022 走看看