题面:

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 ABC, and S, where 1 ≤ A < 32768, 0 ≤ B < 65536, 2 ≤ C < 65536, and 0 ≤ S < CS 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
0

Sample 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 - 题解【二进制】的更多相关文章

  1. POJ - 3652 Persistent Bits

    “模拟”类型,题型容易,使用bitset库对二进制逐位操作,初始化.十进制转二进制(unsigned int).位操作. POJ - 3652 Persistent Bits Time Limit:  ...

  2. POJ 3652 &amp; ZOJ 2934 &amp; HDU 2721 Persistent Bits(数学 元)

    主题链接: PKU:http://poj.org/problem?id=3652 ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do? probl ...

  3. CodeForces 485C Bits[贪心 二进制]

    C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...

  4. 【HDOJ】2721 Persistent Bits

    题目有点长,但是题意说的很清楚.位操作. #include <stdio.h> ]; int main() { int a, b, c, s; int i, j, k, n, tmp, m ...

  5. 【BZOJ5294】[BJOI2018]二进制(线段树)

    [BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...

  6. Tyvj3308毒药解药题解

    题目大意 这些药都有可能在治愈某些病症的同一时候又使人患上某些别的病症--经过我天才的努力.最终弄清了每种药的详细性能,我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要依据这张清单 ...

  7. LeetCode编程训练 - 位运算(Bit Manipulation)

    位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...

  8. C#版 - Leetcode 191. Number of 1 Bits-题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. 算法与数据结构基础 - 位运算(Bit Manipulation)

    位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...

随机推荐

  1. 使用digispark制作一个BadUSB

    0X00.工具准备 digispark开发板. 淘宝连接:https://m.tb.cn/h.VK7vwjy?sm=d85844 0X01.安装Arduino IDE环境 1.安装 arduino 的 ...

  2. GeneralUpdate20220323里程碑版本发布

    大家好我是juster,GeneralUpdate的开源项目作者.这次将发布GeneralUpdate里程碑版本,该版本发生了巨大改变历时4个月的时间终于要和大家见面了.开源不易希望大家能多多支持.可 ...

  3. Java中实现多态的机制是什么?

    Java允许父类或接口定义的引用变量指向子类或具体实现类的实例对象,而程序调用的方法在运行时才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类 ...

  4. SQL 语言包括哪几部分?每部分都有哪些操作关键字?

    SQL 语言包括数据定义(DDL).数据操纵(DML),数据控制(DCL)和数据查询(DQL) 四个部分. 数据定义:Create Table,Alter Table,Drop Table, Crae ...

  5. phpstorm chrome 添加xdebug扩展

    转:https://blog.csdn.net/ltcm_sakura/article/details/102967859 一.Xdebug helper:php调试插件 http://chromec ...

  6. sleep()和wait()的区别?notify()和notifyAll()的区别?start()和run()的区别?

    sleep()和wait()的区别? 这两个方法来自不同的类分别是Thread和Object sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法.wait,not ...

  7. List、Set、Map 是否继承自 Collection 接口?

    List.Set 是,Map 不是.Map 是键值对映射容器,与 List 和 Set 有明显的区别, 而 Set 存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List 是线性结构的容 ...

  8. elasticsearch 的倒排索引是什么 ?

    解答:通俗解释一下就可以. 传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置. 而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表 即为倒排索引. 有了倒排索引,就能实现 ...

  9. 传染病模型(SIR模型)

  10. jquery+html5实现单张图片上传预览

    js: if (window.File && window.FileReader && window.FileList && window.Blob){ ...