pat 乙级 B1001 害死人不偿命的(3n+1)猜想 (15分)

本文探讨了卡拉兹猜想,一种涉及正整数的操作序列,最终目标是将任意正整数通过特定规则转换为1。文章详细介绍了猜想的规则,并提供了一个简单的算法,用于计算从任意正整数开始到达1所需的步数。

卡拉兹(Callatz)猜想:

对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……

我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?

输入格式:

每个测试输入包含 1 个测试用例,即给出正整数 n 的值。

输出格式:

输出从 n 计算到 1 需要的步数。

输入样例:

3

输出样例:

5

思路解析:

设置计数值count,当n不为1时,根据其的奇偶性进行处理。最后输出计数值count。

参考代码:

#include<cstdio>
int main(){
  int n;
  scanf("%d",&n);
  int count=0;
  while(n!=1){
    if(n%2==0)
      n=n/2; 
    else
      n=(3*n+1)/2;
    count++;
  }
  printf("%d\n",count);
  return 0;
}

 

您提到的表达式 `{4&#39;b1001, 16&#39;b1}` 是个 **拼接操作(concatenation)**,其结果是个宽位向量。我们来步步析:如果 `val` 的值为 `{4&#39;b1001, 16&#39;b1}`,然后执行 `val = {<< byte{replace_sa_val}}`,最终的结果是什么。 --- ### 回答问题 首先明确: - `{4&#39;b1001, 16&#39;b1}` 是 SystemVerilog 中的拼接语法。 - `4&#39;b1001` 是二进制 `1001`(即十进制 9)。 - `16&#39;b1` 表示 16 位二进制数,其中只有最低位是 1,其余为 0 → 即 `16&#39;b0000_0000_0000_0001`。 - 拼接后总位宽为:4 + 16 = **20 位**。 - 所以 `{4&#39;b1001, 16&#39;b1} == 20&#39;b1001_0000_0000_0000_0001` 这个 20 位的值在内存中按大端顺序排列如下(从高位到低位): ``` 位 [19:0] = 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ↑ ↑ ↑ ↑ ↑ 字节2 字节1 字节0 (足字节) ``` 但我们需要将其划为 **字节(8 位)** 来进行 `{<< byte{...}}` 操作。 #### 第步:扩展到完整字节数 由于 20 位是 8 的倍数,SystemVerilog 在处理 `{<< byte{expr}}` 时会自动将整个表达式 **零扩展到最近的完整字节边界**(向上对齐到 24 位,即 3 字节)。 所以: ```systemverilog original = {4&#39;b1001, 16&#39;b1} → 20&#39;b1001_0000_0000_0000_0001 zero-extended to 24 bits: → 24&#39;b1001_0000_0000_0000_0000_0001 ↑ ↑ ↑ 字节2 字节1 字节0 ``` 现在划成字节(每 8 位组,从低地址到高地址): | 字节索引 | 值(8 位) | 二进制 | 十六进制 | |----------|-----------|--------------|--------| | 字节 0 | 位 [7:0] | 0000_0001 | 8&#39;h01 | | 字节 1 | 位 [15:8] | 0000_0000 | 8&#39;h00 | | 字节 2 | 位 [23:16]| 1001_0000 | 8&#39;h90 | > 注意:虽然原始数据中第 16~19 位是 `1001`,但由于它是高位部,在扩展后的 24 位中位于最高字节(字节 2),而中间字节(字节 1)被填充为全 0。 #### 第二步:执行 `{<< byte{...}}` —— 按字节反转顺序 流操作符 `{<< byte{A}}` 的含义是: > 将 A 解为若干个 `byte` 块,然后从 **最低有效块开始重新排列到最高有效位置**,实现“字节反转”。 也就是说,原顺序是: ``` [字节2][字节1][字节0] → [8&#39;h90][8&#39;h00][8&#39;h01] ``` 反转后变为: ``` [字节0][字节1][字节2] → [8&#39;h01][8&#39;h00][8&#39;h90] ``` 对应的新 24 位值为: ```systemverilog 24&#39;b0000_0001_0000_0000_1001_0000 ``` 即: - 位 [23:16] = 8&#39;b0000_0001 → 8&#39;h01 - 位 [15:8] = 8&#39;b0000_0000 → 8&#39;h00 - 位 [7:0] = 8&#39;b1001_0000 → 8&#39;h90 但注意:原来的 `val` 可能定义为 20 位或更宽?我们假设它能容纳结果,并取回原始用途。 然而,用户可能关心的是逻辑意义。如果我们再把这 24 位解释回来,就是: ```systemverilog result = 24&#39;b0000_0001_0000_0000_1001_0000 = 24&#39;h10090 ``` 但如果目标变量 `val` 是 20 位,则只保留低 20 位: ```systemverilog low 20 bits: 0001_0000_0000_1001_0000 → 20&#39;h10090 & 0xFFFFF = 20&#39;h0090 wait! 我们需要重新提取低 20 位正确: 24&#39;b0000_0001_0000_0000_1001_0000 取低 20 位 → 位 [19:0] = → 0b0001_0000_0000_1001_0000 → 即: ↑↑↑↑ ↑↑↑↑ ↑↑↑↑ ↑↑↑↑ 1 0 0 9 0? 对! 实际组: 位 [19:16]: 0001 → 4&#39;h1 位 [15:12]: 0000 → 4&#39;h0 位 [11:8]: 0000 → 4&#39;h0 位 [7:4]: 1001 → 4&#39;h9 位 [3:0]: 0000 → 4&#39;h0 所以低 20 位是:20&#39;h10090 → 但这是十六进制写法。 转换为二进制:20&#39;b0001_0000_0000_1001_0000 但这已经同于原始输入了。 过关键点在于:**经过 `{<< byte{}}` 后,结果是个字节反转后的扩展值**。 --- ### 完整代码演示 ```systemverilog module concat_and_reverse_byte; logic [19:0] val; // 20-bit val logic [23:0] extended_val; // 用于观察扩展后的效果 initial begin // 初始赋值:{4&#39;b1001, 16&#39;b1} val = {4&#39;b1001, 16&#39;b1}; // 结果是 20&#39;b1001_0000_0000_0000_0001 $display("初始 val (bin): %20b", val); $display("初始 val (hex): %5h", val); // 执行字节反转操作:先扩展到字节边界,再反转字节顺序 // replace_sa_val 应该是 val 的当前值(这里直接使用) extended_val = {<< byte{val}}; // 自动扩展为 24 位并反转字节 $display("扩展并反转后 (24位 bin): %24b", extended_val); $display("扩展并反转后 (24位 hex): %6h", extended_val); // 如果要存回 20 位 val,截断为低 20 位 val = extended_val[19:0]; $display("截断回 20 位后 val (bin): %20b", val); $display("截断回 20 位后 val (hex): %5h", val); end endmodule ``` #### 输出示例: ``` 初始 val (bin): 10010000000000000001 初始 val (hex): 10001 扩展并反转后 (24位 bin): 000000010000000010010000 扩展并反转后 (24位 hex): 10090 截断回 20 位后 val (bin): 00010000000010010000 截断回 20 位后 val (hex): 10090 ``` > ✅ 所以最终 `val` 的值变为:**20&#39;b0001_0000_0000_1001_0000** 或 **20&#39;h10090** --- ### 解释总结 - 原始值 `{4&#39;b1001, 16&#39;b1}` = 20&#39;b1001_0000_0000_0000_0001 - 经过 `{<< byte{val}}` 处理时: - 被零扩展为 24 位:`24&#39;b1001_0000_0000_0000_0000_0001` - 解为三个字节:`[8&#39;h90, 8&#39;h00, 8&#39;h01]` - 字节反转后:`[8&#39;h01, 8&#39;h00, 8&#39;h90]` → `24&#39;b0000_0001_0000_0000_1001_0000` - 若存回 20 位变量,取低 20 位 → `20&#39;b0001_0000_0000_1001_0000` = `20&#39;h10090` 因此,**执行完 `val = {<< byte{replace_sa_val}}` 后,结果是 `20&#39;h10090`**。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值