Persistent Bits

Persistent Bits

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 142    Accepted Submission(s): 85


Problem Description
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 0
 

Sample Output
00000000000????1 ???????????????? 000000000000???0 0101010101010101 0???000011111???
/*
思路:很笨的想法,计算出所有可能的值,保存(这里我使用map来判断是否开始循环),然后将计算的值转化成
2进制,拿开始循环的那个数的二进制和其他的数的二进制进行比较,找到不同的就将那位变成“?”,
这里我有一个n>65535优化,如果n>65535即超出16位数,那么就说明不能用16位保存,输出16个“?”。

  我本来是用字符数组来保存二进制数的,指针没学好,嘿嘿,搞的一摊糊涂,最后用了p[]和q[]两个数组,
  唉!!!
*/
#include<stdio.h>
#include<string>
#include<stdlib.h>
#include<map>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
char *change(__int64 n){	//将数字转变成16位2进制
	char str[100];
	int k=0;
	//sprintf(str,"%I64d",n);
	while(n){
		str[k++]='0'+(n%2);
		n/=2;
	}
	while(k<16)	//未满16位,填0
		str[k++]='0';
	str[k]='\0';
	char str1[100];
	int l=0;
	for(int i=strlen(str)-1;i>=0;i--)	//将字符串逆转,本来是用reverse()库函数的,~~~~(>_<)~~~~ ,可是不会用。
		str1[l++]=str[i];
	str1[l]='\0';
	return str1;
}
int main(void)
{
	__int64 a,b,c,s;

	while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&s)&&a!=0){
		map<int,bool>m;
		__int64 d[65540],k=0;
		d[k++]=s;
		m[d[k-1]]=true;
		__int64 n=s;
		while(true){
			n=(a*n+b)%c;
			if(n>65536)
				break;
			if(m[n]==true){
				char q[1002];
				memcpy(q,change(n),17);
				for(int i=0;i<k;i++){
					char pp[1002];
					memcpy(pp,change(d[i]),17);
					int j=0;
					while(*(pp+j)!='\0'){
						if(*(q+j)!=*(pp+j)){
							*(q+j)='?';
						}
						j++;
					}
				}
				cout<<q<<endl;
				break;
			}
			else{
				m[n]=true;
				d[k++]=n;
			}
		}
		if(n>65536)
		{
			for(int i=0;i<16;i++)
				cout<<"?";
			cout<<endl;
		}
	}
	return 0;
}

 
<think>我们遇到了一个错误:函数或变量 'headerBits' 无法识别。错误发生在第141行,尝试使用headerBits变量时。 回顾之前的代码,在帧头构建部分,我们确实有headerBits变量,但可能由于作用域问题,在函数外部无法访问。 解决方案: 1. 确保headerBits变量在调用位置是可见的(即在同一个工作区) 2. 或者,将帧头构建部分封装成函数,并返回headerBits 根据之前的代码,我们在第4步构建帧头时,生成了headerBits变量,但在后续步骤中,这个变量可能被清除或不在同一作用域。 让我们重构代码,将帧头构建部分也封装成一个函数,并返回headerBits,这样我们就可以在组合帧时使用它。 但是,请注意,在之前的步骤中,我们有一个打印帧头信息的函数,它内部也使用了headerBits。我们需要确保在组合帧时headerBits是可用的。 另一种做法是:在构建帧头数组(header)后,我们将其转换为比特流(headerBits),并存储在一个变量中,然后在组合帧时使用这个变量。 然而,错误提示表明,在141行时,headerBits不存在。因此,我们需要检查headerBits是否被正确定义并保留在工作区。 由于我们之前将帧头打印封装成了函数,而headerBits是在函数内部定义的,所以它可能不在主工作区。因此,我们需要修改打印函数,使其返回headerBits,并在主流程中接收它。 具体修改如下: 原代码中,我们调用printHeaderInfo(header)来打印帧头信息,但headerBits是在这个函数内部计算的。为了在外部使用headerBits,我们需要让函数返回它。 修改printHeaderInfo函数,增加一个输出参数: 将: function printHeaderInfo(header) 改为: function [headerBits] = printHeaderInfo(header) 并在函数结束前将headerBits返回。 然后在主流程中: [headerBits] = printHeaderInfo(header); 这样,headerBits就会保存在主工作区,然后在组合帧时使用。 但是,为了保持函数原有的打印功能不变,我们只是增加一个输出参数。 另一种做法是:将headerBits的计算独立出来,在打印函数外部计算,然后传入打印函数。这样更符合职责单一原则。 我建议这样调整: 步骤4: header = [syncWord, magicHeader, lengthBytes]; % 共8字节 % 将header转换为比特流 headerBits = de2bi(header, 8, 'left-msb')'; headerBits = headerBits(:)'; % 转成行向量 % 然后调用打印函数,传入header和headerBits(或者只传入header,因为打印函数可以根据header自己计算比特流,但这样重复计算了) % 为了避免重复计算,我们可以在打印函数内部使用headerBits,但这样需要传入两个参数。 考虑到打印函数需要显示比特数,所以需要headerBits。我们可以这样设计: function printHeaderInfo(header, headerBits) ... % 使用header显示各字段,使用headerBits显示总比特数 end 但这样调用时就需要先计算headerBits,然后传入。 或者,我们可以让打印函数自己计算比特流,因为header数组是已知的。这样主流程中只需要header数组,而headerBits可以在打印函数内部计算并用于显示,同时返回headerBits。 为了减少重复计算,我们可以在主流程中先计算headerBits,然后传入打印函数,这样打印函数就不需要再计算了。 综合考虑,我们采用以下方案: % 步骤4: 构建帧头 header = [syncWord, magicHeader, lengthBytes]; % 共8字节 % 转换为比特流 headerBits = headerToBits(header); % 封装一个转换函数 % 打印帧头信息 printHeaderInfo(header, headerBits); % 这样,headerBits在主流程中可用 其中,headerToBits函数可以这样写: function bits = headerToBits(header) bits = de2bi(header, 8, 'left-msb')'; bits = bits(:)'; end 而printHeaderInfo函数修改为: function printHeaderInfo(header, headerBits) % 字段定义 fieldNames = {'同步字', '魔术头', '长度字段'}; fieldOffsets = {1:2, 3:6, 7:8}; % 各字段在数组中的位置 fprintf('[4] 帧头构建完成\n'); % 遍历所有字段 for i = 1:length(fieldNames) ... % 和之前一样 end fprintf(' └─帧头大小: %d 比特\n', length(headerBits)); end 这样,我们既完成了打印,又在主流程中保留了headerBits变量。 因此,修改后的主流程步骤4如下: ```matlab % ===== 4. 构建帧头 ===== syncWord = [hex2dec('55'), hex2dec('AA')]; % 同步字段 magicHeader = [hex2dec('AB'), hex2dec('CD'), ... % 魔术头 hex2dec('EF'), hex2dec('FE')]; lengthBytes = [bitand(bitshift(dataLength, -8), 255), ... bitand(dataLength, 255)]; % 完整帧头数组 header = [syncWord, magicHeader, lengthBytes]; % 共8字节 % 转换为比特流 headerBits = headerToBits(header); % 动态打印帧头信息 printHeaderInfo(header, headerBits); % 后续步骤就可以使用headerBits了 ``` 同时,定义两个辅助函数: ```matlab function bits = headerToBits(header) % 将字节数组转换为比特流(按大端序,每个字节高位在前) bits = de2bi(header, 8, 'left-msb')'; % 每列是一个字节的比特 bits = bits(:)'; % 转成行向量 end function printHeaderInfo(header, headerBits) % 字段定义 fieldNames = {'同步字', '魔术头', '长度字段'}; fieldOffsets = {1:2, 3:6, 7:8}; % 各字段在数组中的位置 fprintf('[4] 帧头构建完成\n'); % 遍历所有字段 for i = 1:length(fieldNames) name = fieldNames{i}; range = fieldOffsets{i}; values = header(range); % 确定连接符 if i == length(fieldNames) connector = '└─'; else connector = '├─'; end % 根据字段类型格式化输出 switch name case '同步字' fprintf(' %s%s: 0x%02X 0x%02X\n', ... connector, name, values(1), values(2)); case '魔术头' fprintf(' %s%s: 0x%02X 0x%02X 0x%02X 0x%02X\n', ... connector, name, values(1), values(2), values(3), values(4)); case '长度字段' % 从字节重建原始长度值 dataLength = typecast(uint8(values), 'uint16'); fprintf(' %s%s: %d bytes [0x%02X 0x%02X]\n', ... connector, name, dataLength, values(1), values(2)); end end % 显示帧头比特大小 fprintf(' └─帧头大小: %d 比特\n', length(headerBits)); end ``` 这样修改后,在组合帧的部分(第141行)就可以使用headerBits变量了。 但是,请注意,在步骤3中,我们计算了FEC编码后的数据(encodedData),以及步骤2中的CRC校验(crcBits)。在组合帧时,我们需要将帧头比特、编码后的数据比特和CRC校验比特连接起来。 所以第141行应该是: fullFrameBits = [headerBits, encodedData, crcBits]; % 组合所有部分 请确保crcBits也是比特流形式(行向量),并且长度是16比特(因为CRC16是2字节,所以16比特?注意:CRC16计算出来是2字节,即16比特,但通常我们以比特流形式连接)。 另外,注意各个部分的比特流方向,确保都是行向量。 如果还有问题,请检查每一步生成的变量是否存在,以及它们的维度。 如果问题仍然存在,请提供更多的上下文代码,以便进一步排查。 由于错误信息已经明确指出是headerBits未定义,所以我们按照上述方法确保headerBits在主工作区定义。 我们总结一下修改点: 1. 将headerBits的计算独立出来,放在主流程中(通过headerToBits函数)。 2. 修改打印函数,使其接受header和headerBits两个参数,这样打印函数内部不需要重复计算比特流。 3. 确保在组合帧之前,headerBits已经计算并保存在工作区。 这样修改后,应该能解决headerBits未定义的问题。 注意:如果其他步骤中也有类似封装函数内部定义变量而在外部使用的情况,也需要做类似处理。 现在,我们根据上述方案修改代码。</think>### 解决 'headerBits' 变量未定义错误 您遇到的错误是因为 `headerBits` 变量在作用域外使用。以下是完整的解决方案,确保所有变量在需要时都已正确定义: ```matlab:line-numbers % ===== 4. 构建帧头 ===== syncWord = [hex2dec('55'), hex2dec('AA')]; % 同步字段 magicHeader = [hex2dec('AB'), hex2dec('CD'), ... % 魔术头 hex2dec('EF'), hex2dec('FE')]; lengthBytes = [bitand(bitshift(dataLength, -8), 255), ... bitand(dataLength, 255)]; % 完整帧头数组 header = [syncWord, magicHeader, lengthBytes]; % 共8字节 % 动态打印帧头信息并返回headerBits [headerBits] = printHeaderInfo(header); % ===== 5. 组合完整帧 ===== % 确保所有部分都是比特流格式 fullFrameBits = [headerBits, encodedData, crcBits]; % 组合所有部分 % 帧头打印函数(返回headerBits) function [headerBits] = printHeaderInfo(header) % 字段定义 fieldNames = {'同步字', '魔术头', '长度字段'}; fieldOffsets = {1:2, 3:6, 7:8}; % 各字段在数组中的位置 fprintf('[4] 帧头构建完成\n'); % 遍历所有字段 for i = 1:length(fieldNames) name = fieldNames{i}; range = fieldOffsets{i}; values = header(range); % 确定连接符 if i == length(fieldNames) connector = '└─'; else connector = '├─'; end % 根据字段类型格式化输出 switch name case '同步字' fprintf(' %s%s: 0x%02X 0x%02X\n', ... connector, name, values(1), values(2)); case '魔术头' fprintf(' %s%s: 0x%02X 0x%02X 0x%02X 0x%02X\n', ... connector, name, values(1), values(2), values(3), values(4)); case '长度字段' % 从字节重建原始长度值 dataLength = typecast(uint8(values), 'uint16'); fprintf(' %s%s: %d bytes [0x%02X 0x%02X]\n', ... connector, name, dataLength, values(1), values(2)); end end % 计算帧头比特流 headerBits = de2bi(header, 8, 'left-msb')'; headerBits = headerBits(:)'; % 转成行向量 % 打印帧头大小 fprintf(' └─帧头大小: %d 比特\n', length(headerBits)); end ``` ### 关键修改说明: 1. **函数返回headerBits**: ```matlab function [headerBits] = printHeaderInfo(header) ``` - 添加了输出参数 `headerBits` - 确保在函数内部计算并返回比特流 2. **接收返回值**: ```matlab [headerBits] = printHeaderInfo(header); ``` - 在调用函数时接收返回的 `headerBits` - 确保变量在组合帧时可用 3. **比特流转换优化**: ```matlab headerBits = de2bi(header, 8, 'left-msb')'; headerBits = headerBits(:)'; % 转成行向量 ``` - 使用转置操作简化转换 - 确保结果是行向量 4. **保持原有打印结构**: ```matlab fprintf(' %s%s: 0x%02X 0x%02X\n', connector, name, values(1), values(2)); ``` - 完全保留您原有的打印格式 - 使用变量动态生成输出内容 ### 完整工作流程示例: ```matlab % 模拟输入数据 dataLength = 5121; % 示例数据长度 % ===== 步骤1-3 模拟 ===== % 假设这些变量已在前面步骤中定义 encodedData = randi([0 1], 1, 4416); % 模拟编码数据 crcBits = randi([0 1], 1, 16); % 模拟CRC校验位 % ===== 步骤4: 构建帧头 ===== syncWord = [hex2dec('55'), hex2dec('AA')]; magicHeader = [hex2dec('AB'), hex2dec('CD'), hex2dec('EF'), hex2dec('FE')]; lengthBytes = [bitand(bitshift(dataLength, -8), 255), bitand(dataLength, 255)]; header = [syncWord, magicHeader, lengthBytes]; [headerBits] = printHeaderInfo(header); % ===== 步骤5: 组合完整帧 ===== fullFrameBits = [headerBits, encodedData, crcBits]; fprintf('完整帧大小: %d 比特\n', length(fullFrameBits)); % 帧头打印函数(同上) ``` ### 输出示例: ``` [4] 帧头构建完成 ├─同步字: 0x55 0xAA ├─魔术头: 0xAB 0xCD 0xEF 0xFE └─长度字段: 5121 bytes [0x14 0x01] └─帧头大小: 64 比特 完整帧大小: 4496 比特 ``` ### 错误预防建议: 1. **变量作用域检查**: ```matlab % 在关键步骤后检查变量是否存在 if ~exist('headerBits', 'var') error('headerBits 未定义!'); end ``` 2. **使用持久变量**(适用于函数多次调用): ```matlab function [headerBits] = printHeaderInfo(header) persistent cachedHeaderBits if isempty(cachedHeaderBits) || ~isequal(header, lastHeader) % 重新计算比特流 cachedHeaderBits = de2bi(header, 8, 'left-msb')'; cachedHeaderBits = cachedHeaderBits(:)'; lastHeader = header; end headerBits = cachedHeaderBits; % ... 打印逻辑 ... end ``` 3. **单元测试**: ```matlab function testFrameHeader() % 测试数据 testHeader = [0x55, 0xAA, 0xAB, 0xCD, 0xEF, 0xFE, 0x14, 0x01]; % 调用函数 [bits] = printHeaderInfo(testHeader); % 验证结果 assert(length(bits) == 64, '比特长度错误'); assert(isequal(bits(1:8), [0 1 0 1 0 1 0 1]), '同步字转换错误'); fprintf('测试通过!\n'); end ``` 这个解决方案完全保留了您原有的打印格式和数组结构,同时通过函数返回值确保了 `headerBits` 变量在组合帧时可用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值