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 ...
随机推荐
- 1分钟为Win10瘦身!把吃掉的硬盘找回来
很多小伙伴升级完Win10后都发现C盘变小了,不少人以为这大概就是Win10太占磁盘空间了.但事实上,Win10和以前的操作系统一样,对于C盘空间并没有什么太高要求.出现这个问题的主要原因,是Win1 ...
- C++设计模式 - 访问器模式(Visitor)
行为变化模式 在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化."行为变化" 模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合. 典型模 ...
- Java基础 (上)
基础概念与常识 Java 语言有哪些特点? 简单易学: 面向对象(封装,继承,多态): 平台无关性( Java 虚拟机实现平台无关性): 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操 ...
- ISR、OSR、AR 是什么?
ISR:In-Sync Replicas 副本同步队列 OSR:Out-of-Sync Replicas AR:Assigned Replicas 所有副本 ISR是由leader维护,followe ...
- vue使用svg,animate事件绑定无效问题及解决方法
由于使用svg制作圆形进度条,但是进度展示的太生硬,没有过渡圆滑的效果,所以使用 animate(在svg元素里可以查到) 元素标签,但 这样使用了,还是没有效果,我前端使用的 vue ,所以通过 @ ...
- memcached 和 MySQL 的 query ?
cache 相比,有什么优缺点? 把 memcached 引入应用中,还是需要不少工作量的.MySQL 有个使用方便的 query cache,可以自动地缓存 SQL 查询的结果,被缓存的 SQL 查 ...
- Contos 安装nodeJs环境
1.去nodeJs官网选择版本: https://nodejs.org/en/download/ 选择64位,右键复制链接地址 https://nodejs.org/dist/v8.12.0/node ...
- I2C总线完全版——I2C总线的结构、工作时序与模拟编程
I2C总线的结构.工作时序与模拟编程 I2C总线的结构.工作时序与模拟编程I2C总线(Inter Integrated Circuit)是飞利浦公司于上个世纪80年代开发的一种"电路板级&q ...
- C#通过LDAP访问目录服务
C#通过LDAP访问目录服务 本文介绍如何编写C#程序通过LDAP协议访问微软目录服务获得用户在目录中的属性信息.在开始部分先简单句介绍LDAP协议,然后是技术比较及实现部分. 目录 什么是LDAP? ...
- 用CSS实现Tab页切换效果
用CSS实现Tab切换效果 最近切一个页面的时候涉及到了一个tab切换的部分,因为不想用js想着能不能用纯CSS的选择器来实现切换效果.搜了一下大致有下面三种写法. 利用:hover选择器 缺点:只有 ...