一、题目详情
问题描述:害死人不偿命的(3n+1)猜想
卡拉兹(Callatz)猜想:对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……
我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?
输入格式:
每个测试输入包含 1 个测试用例,即给出正整数 n 的值。
输出格式:
输出从 n 计算到 1 需要的步数。
输入样例:
3
输出样例:
5
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
二、题目解析
代码:
#include <stdio.h>
int main()
{
/*
* n:输入的正整数
* step:记录步数,初始化为0
*/
int n, step = 0;
scanf("%d", &n);
while(n != 1)
{
if(n % 2 == 0)//偶数
n /= 2;
else//奇数
n = (3 * n + 1) / 2;
step++;//步数累加
}
printf("%d", step);
return 0;
}
提交结果(分数/满分):
15分/15分
提示:
摘自 PAT FAQ:https://pintia.cn/faq
1. IDE 问题
本专栏使用的 IDE 是 Visual C++ 6.0。
2. main() 的问题
错误的例子:
void main()
{
printf("hello\n");
}
正确的做法:
int main()
{
printf("hello\n");
return 0;
}
很多旧的基于Windows的C编译器来写的书还在用void main()
,这是无法接受的。main()
的返回值是有意义的,如果返回的不是0,就表示程序运行过程中错误了,那么服务器上的判题程序也会给出错误的结论。
3. 多余的输出
错误的例子:
int main()
{
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
...
printf("%d和%d的最大公约数是%d\n", a, b, c);
return 0;
}
程序中不要有任何用户友好性的提示等的输出,只能严格按照题目中所规定的输出格式的要求来输出。
你可以运行自己的程序,用题目中的输入样例来输入,如果得到的输出和输出样例完全相同,一个字符也不多,一个字符也不少,那么这样的格式就是对的。
4. 输出格式问题
仔细阅读题目中对于输出格式的要求。因为在服务器上程序是严格地按照预设的输出来比对你的程序的输出。
常见的输出格式问题包括:
- 行末要求不带空格(或带空格)
- 输出要求分行(或不分行)
- 有空格没空格要看仔细
- 输出中的标点符号要看清楚,尤其是绝对不能用中文全角的标点符号,另外单引号“'”和一撇“`”要分清楚
- 当输出浮点数时,通常题目中会做适当处理,要求比较明确的输出格式,一定要严格遵守,因为浮点数会涉及到输出的精度问题
- 当输出浮点数时,如果可能输出
0
,而数据可能为负时,有可能出现输出-0.0
的情况,需要自己写代码判断,保证不出现-0.0
5. 不能用的库函数
某些库函数因为存在安全隐患是不能用的,目前主要常见的是itoa
和gets
。