Persistent Bits - 题解【二进制】
题面:
WhatNext Software creates sequence generators that they hope will produce fairly random sequences of 16-bit unsigned integers in the range 0–65535. In general a sequence is specified by integers A, B, C, and S, where 1 ≤ A < 32768, 0 ≤ B < 65536, 2 ≤ C < 65536, and 0 ≤ S < C. S is the first element (the seed) of the sequence, and each later element is generated from the previous element. If X is an element of the sequence, then the next element is
(A * X + B) % C
where '%' is the remainder or modulus operation. Although every element of the sequence will be a 16-bit unsigned integer less than 65536, the intermediate result A * X + B may be larger, so calculations should be done with a 32-bit int rather than a 16-bit short to ensure accurate results.
Some values of the parameters produce better sequences than others. The most embarrassing sequences to WhatNext Software are ones that never change one or more bits. A bit that never changes throughout the sequence is persistent. Ideally, a sequence will have no persistent bits. Your job is to test a sequence and determine which bits are persistent.
For example, a particularly bad choice is A = 2, B = 5, C = 18, and S = 3. It produces the sequence 3, (2*3+5)%18 = 11, (2*11+5)%18 = 9, (2*9+5)%18 = 5, (2*5+5)%18 = 15, (2*15+5)%18 = 17, then (2*17+5)%18 = 3 again, and we're back at the beginning. So the sequence repeats the the same six values over and over:
Decimal 16-Bit Binary 3 0000000000000011 11 0000000000001011 9 0000000000001001 5 0000000000000101 15 0000000000001111 17 0000000000010001 overall 00000000000????1 The last line of the table indicates which bit positions are always 0, always 1, or take on both values in the sequence. Note that 12 of the 16 bits are persistent. (Good random sequences will have no persistent bits, but the converse is not necessarily true. For example, the sequence defined by A = 1, B = 1, C = 64000, and S = 0 has no persistent bits, but it's also not random: it just counts from 0 to 63999 before repeating.) Note that a sequence does not need to return to the seed: with A = 2, B = 0, C = 16, and S = 2, the sequence goes 2, 4, 8, 0, 0, 0, ....
Input
There are from one to sixteen datasets followed by a line containing only 0. Each dataset is a line containing decimal integer values for A, B, C, and S, separated by single blanks.
Output
There is one line of output for each data set, each containing 16 characters, either '1', '0', or '?' for each of the 16 bits in order, with the most significant bit first, with '1' indicating the corresponding bit is always 1, '0' meaning the corresponding bit is always 0, and '?' indicating the bit takes on values of both 0 and 1 in the sequence.
Sample Input
2 5 18 3
1 1 64000 0
2 0 16 2
256 85 32768 21845
1 4097 32776 248
0Sample Output
00000000000????1
????????????????
000000000000???0
0101010101010101
0???000011111???
大意:
给定无符号整数 A , B , C 以及一个“种子数据”S ,每一次迭代令 S = ( A * S + B ) % C ,由于 2 ≤ C < 65536 ,所以S的值一定会周期出现。现将S化为16位二进制数,高位0补齐,在循环过程中S未变化的二进制位原样输出,变化的位输出问号。
题解:
16位二进制最大表示的数为十进制的65535,我们在判断S是否周期出现时,开一个大小为65536(索引0~65535)的bool数组就行,迭代过程中如果发现数字重复出现,就退出迭代,寻找没有变化的位。在这里我使用了更加节省空间和时间的STL容器bitset。
bitset<65536> occ;
/*
*一些操作
*/
while (!occ.test(s)) {
occ.set(s);
//对s进行迭代操作
}
bitset的test(s)成员函数作用是对第s位的状态(true , false)进行判断,set(s)函数把第s位设置成true。那么如何判断某一位是否发生了变化呢?
我们定义一个无符号整型变量cmp,将它的前16位全部置为1,要实现这个,只需 cmp = ( 1 << 16 ) - 1即可。1 << 16是二进制下1后接16个0,减去1就是16个1了,简单的二进制减法。
同时我们记录下迭代前的数pre,迭代后的数cur。如何判断它们的二进制位有没有发生变化?我们知道,发生变化无非就是0变成1,1变成0,因此我们只要按位异或,得到的结果中,发生变化的二进制位就是1,没发生变化的就是0 。例如某次变化前为3,变化后为11,即0011 -> 1011 (为叙述方便省略前导0),异或得到的结果就是1000,代表从右往左第4位发生了变化。
接下来,我们如何将这个变化的信息记录在cmp中呢?
我的想法是,变化的位置0,没变化的位置1,因此我对异或的结果取反,即 1111 1111 1111 0111 (在这里,我完整写出了结果)。将这个结果与cmp(二进制表示为 1111 1111 1111 1111 )按位与,就得到了 1111 1111 1111 0111 。变化的信息得以记录,好耶!
接下来,11变化为9,即 1011 -> 1001 ,异或,取反,得到 1111 1111 1111 1101 。将这个结果与现在的cmp按位与。现在的cmp是1111 1111 1111 0111,第四位的0代表在先前的迭代中第4位发生了变化。虽然在这一轮中第四位没有发生变化,但是先前有啊!我们要记录这个信息。按位与之后,只有都是1的位才会被置1,所以未变化的位不受影响,先前变化过,这轮没有变化的位也会被记录下来变化过。因为0和1或者0按位与,结果都是0 。现在得到了 cmp = 1111 1111 1111 0101 ,代表在先前的变化中第2、4位发生了变化。这样下去,一轮下来,cmp的值就是 1111 1111 1111 0001,参考题面。这是实现这一过程的代码。
cmp = (1 << 16) - 1;
while (!occ.test(s)) {
occ.set(s);
cur = s = (a * s + b) % c;
cmp = (~(pre ^ cur))&cmp;//记录下变化的信息。
pre = cur;
}
接下来就是输出了。判断一个位是否发生变化?只要用特定位是1,其余位都是0的数去和它按位与即可。如果结果是0,说明发生了变化,输出“?”。如果结果不为0,说明该位没有发生变化,此时我们随便抓出一个变化过程中的量(毕竟没变化嘛)做按位与,测试它的值,非0输出1,否则输出0,即可。
unsigned bit = 1 << 15;//1000 0000 0000 0000
rep(i, 1, 16) {
if (bit & cmp) {
cout << (bit & pre ? 1 : 0);
} else {
cout << '?';
}
bit >>= 1;//0100 0000 0000 0000
}
cout << endl;
下面就是完整的AC代码啦~
#include <iostream>
#include <cstdio>
#include <bitset>
#include <algorithm>
#define grp int T;cin>>T;while(T--)
#define elif else if
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rrep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
int main() {
unsigned pre;
unsigned cur;
unsigned cmp;
bitset<65536> occ;
unsigned a, b, c, s;
while (cin >> a) {
if (a == 0) break;
cin >> b >> c >> s;
pre = s;
cmp = (1 << 16) - 1;
occ.reset();
while (!occ.test(s) && cmp) {
occ.set(s);
cur = s = (a * s + b) % c;
cmp = (~(pre ^ cur))&cmp;
pre = cur;
}
unsigned bit = 1 << 15;
rep(i, 1, 16) {
if (bit & cmp) {
cout << (bit & pre ? 1 : 0);
} else {
cout << '?';
}
bit >>= 1;
}
cout << endl;
}
return 0;
}
Persistent Bits - 题解【二进制】的更多相关文章
- POJ - 3652 Persistent Bits
“模拟”类型,题型容易,使用bitset库对二进制逐位操作,初始化.十进制转二进制(unsigned int).位操作. POJ - 3652 Persistent Bits Time Limit: ...
- POJ 3652 & ZOJ 2934 & HDU 2721 Persistent Bits(数学 元)
主题链接: PKU:http://poj.org/problem?id=3652 ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do? probl ...
- CodeForces 485C Bits[贪心 二进制]
C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...
- 【HDOJ】2721 Persistent Bits
题目有点长,但是题意说的很清楚.位操作. #include <stdio.h> ]; int main() { int a, b, c, s; int i, j, k, n, tmp, m ...
- 【BZOJ5294】[BJOI2018]二进制(线段树)
[BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...
- Tyvj3308毒药解药题解
题目大意 这些药都有可能在治愈某些病症的同一时候又使人患上某些别的病症--经过我天才的努力.最终弄清了每种药的详细性能,我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要依据这张清单 ...
- LeetCode编程训练 - 位运算(Bit Manipulation)
位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...
- C#版 - Leetcode 191. Number of 1 Bits-题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- 算法与数据结构基础 - 位运算(Bit Manipulation)
位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...
随机推荐
- 内网渗透----域环境搭建(server 2012)
先确定两台服务器相通 1.配置静态IP与DNS 2.配置域服务 点击服务器管理器-添加角色和功能-下一步-添加AD域服务: 3.提升为域控制器 安装完成后,可在旗帜处选择提升为域控制器 添加新林 添加 ...
- MySQL—事务(ACID)
参考CSDN:https://blog.csdn.net/dengjili/article/details/82468576 1.事务四大特性 原子性(Atomicity) 要么都成功,要么都失败. ...
- HarmonyOS USB DDK助你轻松实现USB驱动开发
HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...
- nginx反向代理失败,又是 fastdfs 的锅
fdfs问题记录 [root@hostcad logs]# systemctl status fdfs_trackerd.service ● fdfs_trackerd.service - LSB: ...
- 匿名内部类编译生成的class文件
一.问题描述 跳槽到的新公司,相比原来的公司,软件开发非常不规范,经常各种坑.项目部署到生产现场之后,出现问题,我在修改之后编译生成class文件,然后将class文件发给现场的技术支持,技术支持将c ...
- Java的HashMap是如何工作的?
HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 get ()方法储存和获取对象.当我们将键值对 ...
- MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐 级之间的区别?
SQL 标准定义的四个隔离级别为: 1.read uncommited :读到未提交数据 2.read committed:脏读,不可重复读 3.repeatable read:可重读 4.seria ...
- 让你熟知jquery见鬼去吧
$是jquery最具代表的符号,当然php也是,但是二者不能同日而语;不得不说jquery的选择器是大家赞不绝口的,在它1.x版本中对ie兼容性是最好的,这要归功于$选择器; 现在呢,html5的降临 ...
- 《深入理解ES6》笔记—— JavaScript中的类class(9)
ES5中的近类结构 ES5以及之前的版本,没有类的概念,但是聪明的JavaScript开发者,为了实现面向对象,创建了特殊的近类结构. ES5中创建类的方法:新建一个构造函数,定义一个方法并且赋值给构 ...
- Element UI table参数中的selectable的使用
Element UI table参数中的selectable的使用中遇到的坑:页面: <el-table-column :selectable='selectable' type="s ...