【BZOJ-2839】集合计数 容斥原理 + 线性推逆元 + 排列组合
2016-05-10 09:36
447 查看
2839: 集合计数
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 229 Solved: 120
[Submit][Status][Discuss]
Description
一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得它们的交集的元素个数为K,求取法的方案数,答案模1000000007。(是质数喔~)
Input
一行两个整数N,KOutput
一行为答案。Sample Input
3 2Sample Output
6HINT
【样例说明】假设原集合为{A,B,C}
则满足条件的方案为:{AB,ABC},{AC,ABC},{BC,ABC},{AB},{AC},{BC}
【数据说明】
对于100%的数据,1≤N≤1000000;0≤K≤N;
Source
Solution
先手推了N=2~3,K的值,又推了推式子,大体上有所发现首先N个元素中交集出现i个元素的的方案数为$C^{i}_{n}$
那么剩下$2^{n-i}$个其他集合,任选的方案总数为$2^{2^{n-1}-1}$种
最后统计答案$\sum_{k<=i<=N}(-1)^{i-k}*C^{i}_{n}*C^{k}_{i}*(2^{2^{n-i}-1})$
数据范围明显不能直接预处理C,所以先预处理阶乘和逆元再计算C即可
Code
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int N,K; const long long p=1e9+7; #define maxn 1000010 long long inv[maxn],fac[maxn],ans; void GetInv() {inv[1]=1;for (int i=2; i<=N; i++) inv[i]=(p-p/i)*inv[p%i]%p;} void Prework() {inv[0]=1;for (int i=1; i<=N; i++)inv[i]=inv[i]*inv[i-1]%p;} void GetFac() {fac[0]=1;for (int i=1; i<=N; i++) fac[i]=(long long)fac[i-1]*i%p;} long long C(long long n,long long m) {return fac *inv[m]%p*inv[n-m]%p;} int main() { scanf("%d %d",&N,&K); GetFac(); GetInv(); Prework(); for (long long i=N,tmp=2; i>=K; i--,tmp=tmp*tmp%p) ans=(ans+((i-K&1?p-1:1)*C(N,i)%p*C(i,K)%p*(tmp+p-1)%p))%p; printf("%lld\n",ans); return 0; }
丧心病狂的压代码
相关文章推荐
- JAVA并发实现五(生产者和消费者模式wait和notify方式实现)
- jQuery对象的链式操作用法分析
- 伊隆·马斯克:亿万富翁段子手,因为他从不掩饰真实的自己
- IDA SIG文件制作 批处理方法
- Java实现定时任务的三种方法
- debstack 安装 openstack
- 通过parent 关键字访问基类的方法和属性 parent.php
- 适配器模式
- Unity3D控制人物移动跳跃,处理CharacterController的isGrounded总是返回false问题
- 事务概念_四大特性
- 表空间 -- tablespace
- 记事本记录日志
- 盖得化工--selenium翻页测试
- Jquery Ajax--- get,post,ajax方法返回json数据
- 区块链倡导者在自由党选举大会上畅想完美选举
- Xposed模块开发入门教程
- 设置fb player版本
- Xcode屏幕截图
- 移动端h5页面帮助资料干货
- C++中的类所占内存空间