有m种物品,n个箱子之中装着若干物品。问取出一些箱子后,所有m种物品都被选出的方案数。

m<=20,n<=106

这道题很妙啊 深刻地利用了容斥

看到n=20,我们就想到了状压和容斥。

怎么容斥呢?我们设A(s)表示状态为s的集合的数量,那么A(2^m-1)就是所求答案。但是这个不好做,那么我们用容斥放缩一下这个条件。我们设B(s)表示状态为s的子集的集合的数量,那么我们可以得到以111为例 B(111)=A(111)+B(110)+B(101)+B(011)-B(100)-B(010)-B(001)+B(000) 那么化简一下 A(111)=B(111)-B(110)-B(101)-B(011)+B(100)+B(010)+B(001)-B(000) 标准的容斥形式。那么剩下的问题就是求出B的值。

我们定义B(s)是s的子集的集合的数量,那么我们只要枚举s的子集就行了,统计数量只要在读入时统计一下就行了。但是枚举子集的复杂度是3^m,过不去,那么我们再优化。

这里我们用了一种分治的方法来优化复杂度,我们利用一种类似cdq分治的办法,把复杂度优化到m*2^m。具体见代码。

然后就是容斥了。

这里证明一下子集枚举的复杂度:我们不妨设二元对(s,t)。那么我们不妨用三进制来表达关系,0s是t的子集,1s和t没关系,2t是s的子集。那么这就是3^m了。

还有一种可以省去popcount的枚举子集的方法,就是用递归,但是程序中没有实现,想知道的可以留个言教导一下蒟蒻。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = , mod = ;
int n, all, m;
ll ans;
int c[N], d[N];
inline ll power(ll x, ll t)
{
ll ret = ;
for(; t; t >>= , x = x * x % mod) if(t & ) ret = ret * x % mod;
return ret;
}
void build(int l, int r)
{
if(l > r) return;
if(l == r) { c[l] = d[l]; return; }
int mid = (l + r) >> ;
build(l, mid); build(mid + , r);
for(int i = l; i <= mid; ++i) c[i + mid - l + ] = (c[i + mid - l + ] + c[i]) % mod;
}
int main()
{
scanf("%d%d", &n, &m); all = << m;
for(int i = ; i <= n; ++i)
{
int num, tot = ; scanf("%d", &num);
while(num--)
{
int x; scanf("%d", &x); --x;
tot |= ( << x);
}
++d[tot];
}
build(, all - );
for(int i = ; i < all; ++i)
{
int x = __builtin_popcount(i);
if((x % ) == (m % )) ans = (ans + power(, c[i])) % mod; else ans = ((ans - power(, c[i])) % mod + mod) % mod;
}
printf("%lld\n", ans);
return ;
}

COCI2012 TOY的更多相关文章

  1. BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9812  Solved: 3978[Submit][St ...

  2. POJ 2398 Toy Storage(计算几何)

    题意:给定一个如上的长方形箱子,中间有n条线段,将其分为n+1个区域,给定m个玩具的坐标,统计每个区域中的玩具个数. 题解:通过斜率判断一个点是否在两条线段之间. /** 通过斜率比较点是否在两线段之 ...

  3. Codeforces Round #238 (Div. 2) D. Toy Sum(想法题)

     传送门 Description Little Chris is very keen on his toy blocks. His teacher, however, wants Chris to s ...

  4. 【BZOJ-1010】玩具装箱toy DP + 斜率优化

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 8432  Solved: 3338[Submit][St ...

  5. ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

    祝大家新年快乐,相信在新的一年里一定有我们自己的梦! 这是一个简化的魔板问题,只需输出步骤即可. 玩具(Toy) 描述 ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具. 该玩具酷似魔方, ...

  6. [LintCode] Toy Factory 玩具工厂

    Factory is a design pattern in common usage. Please implement a ToyFactory which can generate proper ...

  7. POJ 2398 - Toy Storage 点与直线位置关系

    Toy Storage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5439   Accepted: 3234 Descr ...

  8. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  9. 简单几何(点与线段的位置) POJ 2318 TOYS && POJ 2398 Toy Storage

    题目传送门 题意:POJ 2318 有一个长方形,用线段划分若干区域,给若干个点,问每个区域点的分布情况 分析:点和线段的位置判断可以用叉积判断.给的线段是排好序的,但是点是无序的,所以可以用二分优化 ...

随机推荐

  1. nginx配置文件+本地测试请求转发到远程服务器+集群

    1 在本地测试1 众所周知,nginx是一个反向代理的服务器,主要功能即为实现负载均衡和动静分离.在别的我别的文章有详细的nginx(Windows)相关介绍教程. 由于自己安装的nginx在本地的计 ...

  2. Overload重載和Override重写的区别。Overloaded的方法是否可以改变返回值的类型?

    Overload是重载的意思,Override是覆盖的意思,也就是重写. 重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同). 重写Ove ...

  3. 九度oj 题目1057:众数

    题目1057:众数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:9744 解决:3263 题目描述: 输入20个数,每个数都在1-10之间,求1-10中的众数(众数就是出现次数最多的数, ...

  4. CentOS7使用mount命令来挂载CDROM

    https://blog.csdn.net/testcs_dn/article/details/41448557

  5. UVA 10603_Fill

    题意: 给定三个杯子容量,初始只有第三个杯子满,其余为空,求最少需要倒多少水才能让某一杯子中有d升水,如果不能达到,则小于d且尽量接近. 分析: 因为要求转移水量最少,所以采用优先级队列保存每次的状态 ...

  6. eclipse添加高版本tomcat问题

    eclipse添加高版本tomcat会报错,提示无法匹配高版本的容器installation is expected 解决方法: 1.找到tomcat的lib目录下的catalina.jar包,用压缩 ...

  7. mvnw是什么(Maven Wrapper/Maven保持构建工具版本一直的工具)

    背景 Maven是一款非常流行的Java项目构建软件,它集项目的依赖管理.测试用例运行.打包.构件管理于一身,是我们工作的好帮手,maven飞速发展,它的发行版本也越来越多,如果我们的项目是基于Mav ...

  8. how to read openstack code : routes

    When coding a web system, you have to think about an important problem, how to map urls to logic. Op ...

  9. python中的is判断引用的对象是否一致,==判断值是否相等

    python中的is判断引用的对象是否一致,==判断值是否相等 a = 10 b = 20 list = [1,2,3,4,5] print(a in list) print(b not in lis ...

  10. JAVA获取操作系统的信息

    列出全部信息: Properties prop = System.getProperties(); prop.list(System.out); 获取某个信息: String os = prop.ge ...