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 ...
随机推荐
- 题解0005:数的划分(洛谷P1025)
题目描述:将整数 n 分成 k 份,每份不能为空,颠倒顺序的被看成一种分法. 题目链接:https://www.luogu.com.cn/problem/P1025 题目思路:深搜剪枝,规定搜索的下一 ...
- Linux C申请内存三种基本方式
一份代码可以知道具体方式和原理: int main() { int stack_a; int stack_b; static int static_c; static int static_d; in ...
- 学习Spring资料
参考文档 官方文档 源码分析 书籍 Spring5核心原理与30个类手写实战 Spring技术内幕 视频 bilibili
- Ajax是什么?包含什么技术?有什么作用?
Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写. Ajax 尝试建立桌面应用程序的功能和交互性,与不断更新的 Web 应用程序之间的桥梁.不 ...
- JavaScript ajax返回状态
该内容转自CSDN:http://blog.csdn.net/u013381651/article/details/51261956 xmlhttp.readyState的值及解释: 0:请求未初始化 ...
- Redis的集群搭建(四)
1.redis-cluster架构图 2.redis-cluster投票:容错 架构细节: (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽. (2) ...
- 什么是微服务架构中的 DRY?
DRY 代表不要重复自己.它基本上促进了重用代码的概念.这导致开发和共享库, 这反过来导致紧密耦合.
- 什么是 spring bean?
它们是构成用户应用程序主干的对象. Bean 由 Spring IoC 容器管理. 它们由 Spring IoC 容器实例化,配置,装配和管理. Bean 是基于用户提供给容器的配置元数据创建.
- 学习Python(一)
一.Python的基础 1.Python是怎样的语言? 2.Python的安装 Linux安装(python3) yum install -y make zlib zlib-devel gcc-c++ ...
- Java动态代理和CGLib代理
本文参考 在上一篇"Netty + Spring + ZooKeeper搭建轻量级RPC框架"文章中涉及到了Java动态代理和CGLib代理,在这篇文章中对这两种代理方式做详解 下 ...