TOJ4505: KOSARE
TOJ4505: KOSARE 
Total Submit: 11 Accepted:3
Description
Mirko found N boxes with various forgotten toys at his attic. There are M different toys, numbered 1 through M, but each of those can appear multiple times across various boxes.
Mirko decided that he will choose some boxes in a way that there is at least one toy of each kind present, and throw the rest of the boxes away.
Determine the number of ways in which Mirko can do this.
Input
The first line of input contains two integers N and M (1 ≤ N ≤ 1 000 000, 1 ≤ M ≤ 20).
Each of the following N lines contains an integer Ki (0 ≤ Ki ≤ M) followed by Ki distinct integers from interval [1, M], representing the toys in that box.
Output
The first and only line of output should contain the requested number of ways modulo 1 000 000 007.
Sample Input
3 3
3 1 2 3
3 1 2 3
3 1 2 3
Sample Output
7
Source
你有n个盒子,然后有m种物品。每个盒子各有K个物品,你有多少种方式拿盒子,把东西都拿完
那天我的思路就是去统计这些盒子的状态然后去容斥,显然是爆炸的
这个要用到那个集合的那个知识,n个元素的他的子集有2^n个,也就是幂集,在这个基础上枚举子集容斥就可以省掉很多步骤
来看一下这个状态压缩的道理吧
之前做过求两个数字有相同数位的对数,那个把每个数直接变为2^digit,找到每一位的hash值,然后把每个数都减1,这样1对应1,2对应2,20对应2^19,这些数加起来是2^20-1,所以数组开到1<<20即可
每个盒子所对应的hash值知道了,我要和另一个盒子的东西看他们一样么,可以这样想,和他肯定不同的会是谁呢,就是从L开始到枚举的那个中间值(L+R)>>1,mi+i-L肯定是和i是相关的,要进行加法计算,但是我有些子集是重复的,需要枚举重新减去
#include<stdio.h>
typedef __int64 ll;
const ll MD=1e9+;
ll a[];
ll po(int n)
{
ll ans=,b=;
while(n)
{
if(n&)ans=ans*b%MD;
b=b*b%MD;
n>>=;
}
return ans;
}
void la(int L,int R)
{
if(L+==R)
{
a[L]=po(a[L]);
return;
}
int mi=(L+R)>>;
for(int i=L; i<mi; i++)
a[mi+i-L]+=a[i];
la(L,mi);
la(mi,R);
for(int i=L; i<mi; i++)
{
a[mi+i-L]-=a[i];
if(a[mi+i-L]<)a[mi+i-L]+=MD;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=,k; i<n; i++)
{
scanf("%d",&k);
int f=;
for(int j=,x; j<k; j++)
{
scanf("%d",&x);
f|=(<<(--x));
}
a[f]++;
}
la(,<<m);
printf("%I64d",a[(<<m)-]);
}
这个怎么省去加这个状态呢,就是提前进行一次二进制枚举
#include<stdio.h>
typedef __int64 ll;
const ll MD=1e9+;
ll a[];
ll po(int n)
{
ll ans=,b=;
while(n)
{
if(n&)ans=ans*b%MD;
b=b*b%MD;
n>>=;
}
return ans;
}
void la(int L,int R)
{
if(L+==R)
{
a[L]=po(a[L]);
return;
}
int mi=(L+R)>>;
la(L,mi);
la(mi,R);
for(int i=L; i<mi; i++)
{
a[mi+i-L]-=a[i];
if(a[mi+i-L]<)a[mi+i-L]+=MD;
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int ff=<<m,f;
for(int i=,k; i<n; i++)
{
scanf("%d",&k);
f=;
for(int j=,x; j<k; j++)
{
scanf("%d",&x);
f|=(<<(--x));
}
a[f]++;
}
for(int i=; i<m; i++)
for(int s=; s<ff; s++)
if(s&(<<i))
a[s]+=a[s^(<<i)];
la(,ff);
printf("%I64d",a[ff-]);
}
直接位运算去统计,这个算法速度最快
#include<stdio.h>
const int N=<<,MD=1e9+;
int cnt[N],B[N],n,m,ans[N],f;
int main()
{
scanf("%d%d",&n,&m);
f=<<m;
B[]=;
for(int i=; i<=n; i++)
B[i]=(B[i-]<<)%MD;
for(int i=,t,x,s; i<n; i++)
{
scanf("%d",&t);
s=;
while(t--)
scanf("%d",&x),s|=<<x-;
cnt[s]++;
}
for(int i=; i<m; i++)
for(int s=; s<f; s++)
if(s&<<i)
cnt[s]+=cnt[s^<<i];
for(int s=; s<f; s++)
ans[s]=B[cnt[s]];
for(int i=; i<m; i++)
for(int s=; s<f; s++)
if(s&<<i)
ans[s]=(ans[s]-ans[s^<<i]+MD)%MD;
printf("%d",ans[f-]);
return ;
}
TOJ4505: KOSARE的更多相关文章
随机推荐
- ORA-02273: this unique/primary key is referenced by some foreign keys
关于ORA-02273错误,以前还真没有仔细留意过.昨天遇到了这个问题,遂顺便总结一番,以后遇到这类问题就可以直接用下面方案解决.如下所示,我们首先准备一下测试环境. CREATE TABLE TES ...
- mysql-单表操作
mySql单表操作主要有一下内容: 1.查询:查询又分为几种,范围查询,模糊查询.空值查询.多条件查询 查询的语句格式为:SELECT 字段 1,字段 2,字段 3...FROM 表名 WHERE 条 ...
- HDU 3592 World Exhibition (差分约束,spfa,水)
题意: 有n个人在排队,按照前后顺序编号为1~n,现在对其中某两人的距离进行约束,有上限和下限,表示dis[a,b]<=c或者dis[a,b]>=c,问第1个人与第n个人的距离最多可能为多 ...
- SPOJ SORTBIT Sorted bit squence (数位DP,入门)
题意: 给出一个范围[m,n],按照二进制表示中的1的个数从小到大排序,若1的个数相同,则按照十进制大小排序.求排序后的第k个数.注意:m*n>=0. 思路: 也是看论文的.一开始也能想到是这种 ...
- Installing Apache, PHP, and MySQL on Mac OS X
I have installed Apache, PHP, and MySQL on Mac OS X since Leopard. Each time doing so by hand. Each ...
- 从PEP-8学习Python编码风格
(搬运自我在SegmentFault的博客) 关于空行 类与顶级函数(top-level function)的定义之间应当空两行. 类中的方法之间应当空一行. 方法中的逻辑部分之间可以空一行. 关于原 ...
- 一把剪刀看懂git reset 和它的三个参数
都说git 命令难记且难懂,但是如果从立体的角度看待git与git管理的版本,那么一切都会明朗许多. 大多数的学习教程为了理解git,会绘制几个圆圈的串联,每个圆圈代表一个commit的版本,也就是从 ...
- oracle没有监听和监听程序无法找到适用于客户机连接的例程
1.无监听,可以尝试下以下几种办法: 1)在net manager中重新配置监听.我的net manager监听点开不了,把ADMIN下的listener.ora删掉再去打开试试. 2)cmd中输入n ...
- cocos2dx for lua 摄像机移动
在cocos2dx中,我们想通过移动摄像机来做一些特殊处理,比如将摄像机聚焦在某个物体上,或者摄像机颤抖,摄像机原理观察sprite回收状况等等, 都需要通过相机移动来使用. cocos2dx中的摄像 ...
- 【动态规划】bzoj1705: [Usaco2007 Nov]Telephone Wire 架设电话线
可能是一类dp的通用优化 Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线. 新的电话线架设 ...