●BZOJ 2839 集合计数
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=2839
题解:
容斥原理
真的是神题!!!
定义 f[k] 表示交集大小至少为 k时的方案数
怎么求出这个数组呢?
考虑先确定 k个元素(有C(N,k)种方法),那么还剩下 N-k个元素,
这剩下的 N-k个元素可以得到 2^(N-k)个集合,
然后每个集合可以选或不选,(但不能一个都不选),可以得到 2^(2^(N-k))-1 种选法,
每种选法里面的每个集合都加上那以及固定的 k个元素,
可以发现这所有的选法的交集大小都至少为 k。
所以 f[k]=C(N,k)*(22^(N-k)-1)
但是 f[k]还包含了交集为 k+1,k+2,k+3的方法,要怎么减去才能得到交集恰好为 k的方案数呢?
先看看这样一个结论:
不难发现 每种交集恰好为 k+1的方案都在 f[k]中被计算了 C(k+1,k)次。
怎么理解呢?
每种交集恰好为 k+1的方案(记这种方案为 A)的那 k+1个交集元素,
在计算 f[k] 时都可以从中选出 k个来固定,然后得到方案 A,即 A 方案在f[k]中被重复得到了 C(k+1,k)次。
所以要把重复的减去,容斥系数如下(当前要计算交集大小恰好为 k 的方案数):
f[k] :1
f[k+1] :-C(k+1,k)
f[k+2] :+C(k+2,k)
诶,这个 f[k+2]的系数是怎么得到的呢?
首先 每种交集为 k+2 的方案在 f[k]中重复得了 C(k+2,k)次,所以 -C(k+2,k)
但是因为 f[k+1]的系数为 -C(k+1,k),
虽然我们只想减去 f[k]里重复了C(k+1,k)次的交集大小为 k+1 的方案数,
但是无奈再看看定义,f[k+1]里面还包含了交集大小为 k+2,k+3...的方案
所以在给 f[k+1]乘上系数 -C(k+1,k)时,也把 f[k+1]里面的每种交集大小为 k+2的方案减去了 C(k+1,k)次,
同时每种交集大小为 k+2的方案又在 f[k+1]里面的出现了 C(k+2,k+1)次
所以此时要加上因为 f[k+1]*-C(k+1,k)而减去了的交集大小为k+2的方案数,
即 +C(k+1,k)*C(k+2,k+1)
所以把两个结合起来: -C(k+2,k)+C(k+1,k)*C(k+2,k+1) ,化简即可得到 +C(k+2,k)
类似的可以得到 f[k+3],f[k+4]...的系数 :
f[k] :1
f[k+1] :-C(k+1,k)
f[k+2] :-C(k+2,k)+C(k+1,k)*C(k+2,k+1) = +C(k+2,k)
f[k+3] :-C(k+3,k)+C(k+1,k)*C(k+3,k+1)-C(k+2,k)*C(k+3,k+2) = -C(k+3,k)
f[k+4] :-C(k+4,k)+C(k+1,k)*C(k+4,k+1)-C(k+2,k)*C(k+4,k+2)+C(k+3,k)*C(k+3,k+4) = +C(k+4,k)
......
总的式子为 n
∑ (-1)^(i-k)*C(i,k)*f[i]
i=k
然后逮着式子计算就好了。
另外要先线性预处理出阶乘和阶乘逆元以及f数组,便于使用。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define _ %mod
#define MAXN 1005000
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
const int mod=1000000007;
int w[MAXN],f[MAXN],fac[MAXN],inv[MAXN];
int N,K,ANS;
int C(int n,int m){//n中选 m个
return ((1ll*fac[n]*inv[m])_*inv[n-m])_;
}
int pow(int a,int b){
int now=1;
while(b){
if(b&1) now=(1ll*now*a)_;
a=(1ll*a*a)_;
b>>=1;
}
return now;
}
void pre(int n){
w[0]=2; fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=(1ll*fac[i-1]*i)_;
inv[n]=pow(fac[n],mod-2);
for(int i=n-1;i>=0;i--)
inv[i]=(1ll*inv[i+1]*(i+1))_;
for(int i=1;i<=n;i++)
w[i]=(1ll*w[i-1]*w[i-1])_;
for(int i=0;i<=n;i++)
f[i]=(1ll*(w[n-i]-1)*C(n,i))_;
}
int main()
{
scanf("%d%d",&N,&K);
pre(N);
for(int i=K;i<=N;i++)
ANS=(1ll*C(i,K)*f[i]*((i-K)&1?-1:1)+ANS)_;
ANS=(ANS+mod)_;
printf("%d",ANS);
return 0;
}
●BZOJ 2839 集合计数的更多相关文章
- BZOJ 2839: 集合计数 解题报告
BZOJ 2839: 集合计数 Description 一个有\(N\)个元素的集合有\(2^N\)个不同子集(包含空集),现在要在这\(2^N\)个集合中取出若干集合(至少一个),使得 它们的交集的 ...
- BZOJ 2839: 集合计数 [容斥原理 组合]
2839: 集合计数 题意:n个元素的集合,选出若干子集使得交集大小为k,求方案数 先选出k个\(\binom{n}{k}\),剩下选出一些集合交集为空集 考虑容斥 \[ 交集为\emptyset = ...
- Bzoj 2839 集合计数 题解
2839: 集合计数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 495 Solved: 271[Submit][Status][Discuss] ...
- bzoj 2839 集合计数 容斥\广义容斥
LINK:集合计数 容斥简单题 却引出我对广义容斥的深思. 一直以来我都不理解广义容斥是为什么 在什么情况下使用. 给一张图: 这张图想要表达的意思就是这道题目的意思 而求的东西也和题目一致. 特点: ...
- [BZOJ 2839]集合计数
Description 题库链接 有 \(2^n\) 个集合,每个集合只包含 \([1,n]\) ,且这些集合两两不同.问有多少种选择方法(至少选一个),使得这些集合交集大小为 \(k\) . \(0 ...
- bzoj 2839 : 集合计数 容斥原理
因为要在n个里面选k个,所以我们先枚举选的是哪$k$个,方案数为$C_{n}^k$ 确定选哪k个之后就需要算出集合交集正为好这$k$个的方案数,考虑用容斥原理. 我们还剩下$n-k$个元素,交集至少为 ...
- bzoj 2839 集合计数——二项式反演
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839 设 \( g(i) \) 表示至少有 i 个, \( f(i) \) 表示恰好有 i ...
- bzoj 2839 集合计数 —— 二项式反演
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839 设 \( f(i) \) 为至少 \( i \) 个选择,则 \( f(i) = C_ ...
- bzoj 2839: 集合计数【容斥原理+组合数学】
首先,考虑容斥,我们所要的答案是并集至少有\( k \)个数的方案数减去并集至少有\( k+1 \)个数的方案数加上并集至少有\( k \)个数的方案数-- 在n个数中选i个的方案数是\( C_{n} ...
随机推荐
- Centos6.7的在虚拟机virulBox下的lamp平台的搭建
实验环境: linux:小甲鱼带你学C语言,带你飞的提供的体积比较小的centos6.7和virtualBox mysql,apahce,php是燕十八在Linux基础进阶中提供的安装方式: 结果,安 ...
- List集合就这么简单【源码剖析】
前言 声明,本文用得是jdk1.8 前一篇已经讲了Collection的总览:Collection总览,介绍了一些基础知识. 现在这篇主要讲List集合的三个子类: ArrayList 底层数据结构是 ...
- 敏捷项目需求拆解&发现用户故事
需求文档和敏捷中的Epic,User Story, Task之间是什么关系以及如何将需求文档转换成敏捷方式的描述,指导开发人员. 一直是很多公司团队比较困扰的问题,那么最近笔者为了解决这些问题,上了一 ...
- maven的使用之一简单的安装
首先,我们知道,在传统的项目中,我们会导入一堆的jar包,那样的话,我们会发现我们的jar包的大小已经占了整个项目大小的90%以上,甚至更多,而且,我们的jar包只能自己使用,如果 其他人想用的话,还 ...
- Archaius 原理
Archaius 原理 Archaius是什么? Archaius提供了动态修改配置的值的功能,在修改配置后,不需要重启应用服务.其核心思想就是轮询配置源,每一次迭代,检测配置是否更改,有更改重新更新 ...
- python3全栈开发-面向对象、面向过程
一. 什么是面向对象的程序设计及为什么要有它 1.面向过程 面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种 ...
- POJ-2993 Emag eht htiw Em Pleh---棋盘模拟
题目链接: https://vjudge.net/problem/POJ-2993 题目大意: 输入和输出和这里相反. 思路: 模拟题,没啥算法,直接模拟,不过为了代码精简,还是花了一点心思的 #in ...
- [论文阅读] A Discriminative Feature Learning Approach for Deep Face Recognition (Center Loss)
原文: A Discriminative Feature Learning Approach for Deep Face Recognition 用于人脸识别的center loss. 1)同时学习每 ...
- 非黑即白--谷歌OCR光学字符识别
# coding=utf-8 #非黑即白--谷歌OCR光学字符识别 # 颜色的世界里,非黑即白.computer表示深信不疑. # 今天研究一下OCR光学识别庞大领域中的众多分支里的一个开源项目的一个 ...
- 1102mysql关于SOCK文件的认识
自己原创,只为记录. 当本地登录MySQL的时候提示"Can't connect to local MySQL server through socket"的问题,其实代码是MyS ...