做实验 解题报告(二进制枚举子集)

题目描述

有一天,你实验室的老板给你布置的这样一个实验。
首先他拿出了两个长度为 n 的数列 a 和 b,其中每个 a i 以二进制表示一个集
合。例如数字 5 = (101) [2] 表示集合 {1, 3}。第 i 次实验会准备一个小盒子,里面装
着集合 a i 所有非空子集的纸条。老板要求你从中摸出一张纸条,如果满足你摸出的
纸条是 a i 的子集而不是 a i?b i ,a i?b i +1 ,...,a i?1 任意一个的子集,那么你就要被阿掉;
反之,你就逃过一劫。
令你和老板都没有想到的是,你竟然每次都逃过一劫。在庆幸之余,为了知道
这件事发生的概率,你想要算出每次实验有多少纸条能使你被阿掉

输入格式

第一行一个数字 n。
接下来 n 行,每行两个整数,分别表示 a i 和 b i 。

输出格式

n 行,每行一个数字,表示第 i 次实验能使你被啊掉的纸条数。

样例输入 1

3
7 0
15 1
3 1

样例输出 1

7
8
0
4

数据范围

对于 30% 的数据,n, a i , b i ≤ 100
对于 70% 的数据,n, a i , b i ≤ 60000
对于 100% 的数据,n, a i , b i ≤ 10 5
保证所有的 a i 不重复,b i < i

题解

看上去是可以在线做的
关键是枚举每个数的子集 暴力求二进制下每一位是否为1的话是无法表示一个子集的(反正我不会 大多数人也不会 会也不必要在这个题上)
for(int i=a;i;i=(i-1)&a)就可以枚举了
证明:对于第一个真子集(a-1)&a,这个-1把二进制表示下的a的数值为1的最后一位变成了0,而这一位后面的0都变成了1,再&一下原来的a,后面的1又变回了0,而变为0的那一位就没有变回去
所以这一操作就直接搞掉了最后一个1(看不懂就对着我刚刚说的模拟一遍,eg:10110)
同时可以用一个f数组记录一下该子集的最后出现在哪一个大集合里

代码

#include <cstdio>
#include <cmath>
#define ll long long
#define R register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    while (c>'9'||c<'0') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
const int maxn=1e5+5;
int n,a,b,ans,f[maxn];
void init(){
    n=read();
}
void doit(){
    for (R int i(1);i<=n;++i){
        a=read(),b=read();
        ans=0;
        for (R int j(a);j;j=(j-1)&a){//枚举子集
            if (f[j]<i-b) ++ans;//判断是否在该数的前b个数的子集里
            f[j]=i;
        }
        printf("%d\n",ans);
    }
}
signed main(){
//  file("test");
    init();
    doit();
    return 0;
}

原文地址:https://www.cnblogs.com/ancer/p/11304042.html

时间: 2024-11-05 12:23:06

做实验 解题报告(二进制枚举子集)的相关文章

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

poj1753解题报告(枚举、组合数)

POJ 1753,题目链接http://poj.org/problem?id=1753 题意: 有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑? 思路: 1. 每一个位置只有两种颜色,翻偶数次等于没有翻,所以只有翻基数次对棋盘有影响,即只用考虑一个位置最多翻一次. 2. 一共有16个位置,所以最多翻16次.那么可能翻0次就成功.或者翻1

【UVA】11464-Even Parity(二进制枚举子集)

枚举第一行的所有可能情况,之后根据上面行计算下面行(判断是否冲突),获得最终结果. 14058243 11464 Even Parity Accepted C++ 0.275 2014-08-18 05:14:15 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<stack> #inc

hdu 1557 权利指数 ( 二进制枚举子集) 解题心得

原题: Description 在选举问题中,总共有n个小团体,每个小团体拥有一定数量的选票数.如果其中m个小团体的票数和超过总票数的一半,则此组合为“获胜联盟”.n个团体可形成若干个获胜联盟.一个小团体要成为一个“关键加入者”的条件是:在其所在的获胜联盟中,如果缺少了这个小团体的加入,则此联盟不能成为获胜联盟.一个小团体的权利指数是指:一个小团体在所有获胜联盟中成为“关键加入者”的次数.请你计算每个小团体的权利指数. Input 输入数据的第一行为一个正整数T,表示有T组测试数据.每一组测试数

(二进制枚举子集)买玩具

问题描述 蒜厂幼儿园有 n 个小朋友,每个小朋友都有自己想玩的玩具.身为幼儿园园长的你决定给幼儿园买一批玩具,由于经费有限,你只能买 m 个玩具.已知玩具商店一共卖 k 种玩具,编号为 1,2,3,…k,你让每个小朋友把想玩的玩具编号都写在了纸上.你希望满足尽可能多的小朋友的需求,请计算出最多同时能满足多少个小朋友的玩具需求. 输入格式 第一行,输入三个整数 n,m,k(1≤n≤100,1≤m≤k≤15),中间用空格分开. 接下来 n 行,第 i+1(0≤i< n) 行的第一个数字 ai代表第

二进制枚举子集

思路: 利用二进制的"开关"特性枚举: 具体为:假设给定集合A大小为n,则想象A = {a[0], a[1], ..., a[n-1]}的每个元素对应一个开关位(0或1),0表示不出现,1表示出现: 当每个元素的开关位的值确定时,就得到一个子集,因此共有2^n-1种情况(全0为空集,这里不考虑): 我们利用区间[1, 2^n-1],该区间上的每一个整数对应一个子集,对应方法是遍历该整数二进制表示的每一位: 若该位为1则相应子集中存在对应元素,否则不存在. 代码: #include &l

二进制枚举子集技巧

提供一个神奇的姿势 \(for(int \ i=sta;i;i=i-1\&sta)\) 稍微解释一下了,\(sta\)保存的0,1即为原来的需要求子集的集合,\(i\)即为遍历的子集 我们取的子集即是把当前集的元素取或不取,即\(sta\)的1取或不取 我们减去1,即是把最后一位的1变成0,最后一个1后面的0全变1,和原来的&一下,变的1全回去了,也把最后一位搞成0了 剩下的以此类推就差不多了 原文地址:https://www.cnblogs.com/ppprseter/p/9419344

南阳OJ-91-阶乘之和---二进制枚举(入门)

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=91 题目大意: 给你一个非负数整数n,判断n是不是一些数(这些数不允许重复使用,且为正数)的阶乘之和,如9=1!+2!+3!,如果是,则输出Yes,否则输出No:n<1000000; 思路: 数据量小,直接预处理出所有满足的数,然后直接判断就行了,预处理时用了二进制枚举子集的方式来处理 1 #include<iostream> 2 #include<cstdio>

2016.8.29 解题报告之我会做的题都是简单题

老规矩,要相关资料联系邮箱: 考试分析: 1.  画图确定性质,其实我开始也打算用二进制判重的,但进制题一般不会使状态无法用longlong表示出来,然后那种确定了某种状态以后就排除了无关变量,直接取最优的思路也很不错: 2.  最早入手的题以及死在上面的题,还想了了很久的复杂度证明和对拍,无话可说,希望这次AK之路被断能让我涨一点记性,以后要抓住脑海里的每一点信息(本来还想了longlong这个问题的): 3.  找性质,把在线决策问题转化为线性判断类问题,排除任务之间有一点橡树的关系的无关干