首页 > 代码库 > 每日一练第2天:3n+1问题

每日一练第2天:3n+1问题

猜想 (4) :对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次这样的变换,一定会使n变为1。例如,3→10→5→16→8→4→2→1。输入n,输出变换的次数。n≤109

样例输入:

3

样例输出:

7

 

这道题很简单,只需要一个while循环即可解决:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int n, count = 0;
 6     scanf("%d", &n);
 7     while(n > 1)
 8     {
 9         if(n % 2 == 1)
10             n = n * 3 + 1;
11         else
12             n /= 2;
13         ++count;
14     }
15     printf("%d", count);
16     return 0;
17 }

 

但是上面的代码有个问题,题目中有 n≤109,当输入为987654321时,输出为1,结果显然是错误的。因为987654321时奇数,乘以3再加上1后等于2.962962964x109,已经超过了int32类型的范围 [-2147483648,2147483647],那么可以使用long long 来替代,但是输入时需要使用%lld,或者%I64d。所以为了避免这种不确定性,可以在输入的时候使用32位整数,而计算的时候使用long long。改进后的代码如下:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int n2, count = 0;
 6     scanf("%d", &n2);
 7     long long n = n2;
 8     while(n > 1)
 9     {
10         if(n % 2 == 1)
11             n = n * 3 + 1;
12         else
13             n /= 2;
14         ++count;
15     }
16     printf("%d", count);
17     return 0;
18 }

 

总结:当遇到输入不会超范围,而计算过程可能会超范围时,可以使用一种通用的数据类型来输入,然后使用另外一种范围更大的数据类型来计算。

每日一练第2天:3n+1问题