码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ2339】[HNOI2011]卡农 组合数+容斥

时间:2017-08-15 21:06:42      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:www   line   技术   i++   zoj   print   mil   log   个数   

【BZOJ2339】[HNOI2011]卡农

技术分享

题解:虽然集合具有无序性,但是为了方便,我们先考虑有序的情况,最后将答案除以m!即可。

考虑DP。如果我们已经知道了前m-1个集合,那么第m个集合已经是确定的了。因为内层集合的n个元素可以随便出现,那么总数就是A(2^n-1,m-1)。但是可能存在不合法的情况。

1.在前m-1个集合中,n个数出现的次数已经都是偶数了,那么第m个集合为空,不合法,此时方案数为f[m-1]。
2.第m个集合与之前某个集合相同,那么我们不考虑这两个集合,剩下的方案数为f[i-2];该集合可能是第1...m-1个;该集合可能有2^n-1-(m-2)中情况。所以方案数为f[i-2]*(m-1)*(2^n-1-(m-2))

 

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll mod=100000007;
ll n,m,n2,c,m1;
ll ine[1000010],f[1000010];
int main()
{
	scanf("%lld%lld",&n,&m);
	ll i;
	ine[1]=1;
	for(i=2;i<=m;i++)	ine[i]=(mod-(mod/i)*ine[mod%i]%mod)%mod;
	for(n2=i=1;i<=n;i++)	n2=(n2<<1)%mod;
	n2=(n2-1+mod)%mod,c=1,f[0]=1,f[1]=0,m1=1;
	for(i=2;i<=m;i++)
	{
		c=c*(n2-i+2)%mod,m1=m1*ine[i]%mod;
		f[i]=((c-f[i-1]-f[i-2]*(n2-i+2)%mod*(i-1))%mod+mod)%mod;
	}
	printf("%lld",f[m]*m1%mod);
	return 0;
}

【BZOJ2339】[HNOI2011]卡农 组合数+容斥

标签:www   line   技术   i++   zoj   print   mil   log   个数   

原文地址:http://www.cnblogs.com/CQzhangyu/p/7367412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!