卡拉兹(Callatz)猜想:
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……
我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?
输入格式:
每个测试输入包含 1 个测试用例,即给出正整数 n 的值。
输出格式:
输出从 n 计算到 1 需要的步数。
输入样例:
3
输出样例:
5
思路:
没什么思路,半年没敲代码的我连头文件都快背不出来了
依稀觉得应该要分类讨论
想到的语句有switch-case,if,for-while
很快排除了switch-case:分支无法穷举
算法:
对于 n(不超过 1000 的正整数)
如果它是偶数,那么把它砍掉一半;
n/2
如果它是奇数,那么把 (3n+1) 砍掉一半。
(3*n+1)/2
这样一直反复砍下去,最后一定在某一步得到 n=1。(终止条件)
尝试AC:
(一)
using namespace std;
# include <iostream>
int main()
{
int n;
int num=0;
cin>>n;
while(n<=1000 && n>1)
{
if(n%2==0)
n=n/2;
else
n=(n*3+2)/2; //细心的朋友会发现,我这个公式贯穿始终,都是错的,直到很后面才发现
num++;
}
cout<<num<<endl;
return 0;
}
一直卡在部分正确上,后来发现
测试用例是过了
但是特殊情况 n=1没有考虑!
于是开始一番新的尝试
(二)
using namespace std;
# include <iostream>
int main()
{
int n;
int num=0;
cin>>n;
if(n==1)
num++;
while(n<=1000 && n>0)
{
if(n%2==0)
n=n/2;
else
n=(n*3+2)/2;
num++;
}
cout<<num<<endl;
return 0;
}
开始疯狂报错
到底是什么原因,现在还没想出来
晚上讨教一下朋友再说
于是换了一种思路
(三)
#include <iostream>
using namespace std;
int main()
{
int n;
int num=0;
cin>>n;
if(n<=1000)
{
while(n!=1)
{
if(n%2==0)
n=n/2;
else
n=(n*3+1)/2;
num++;
}
}
cout<<num<<endl;
return 0;
}
当然,我不可能一蹴而就
写出这么简洁,易于理解的代码
这是我多番借鉴的结果
而且借鉴的时候发现自己照着写的代码总是拿不到满分
后来才知道,原来是公式写错了 =-=
……
总结:
做完之后想想
这道题的思路还是很清晰的
也不难啊
是我缺乏练习的缘故
脑子懵懵的
有想法,但是没办法捋出来
还是要多敲
sad