UVa——100 - The 3n + 1 problem(打表)
解题思路:这道题题意很明确,就是从整数 n 开始,如果 n 是偶数,把它除以 2;如果 n 是奇数,把它乘 3 加 1。用新得到的值重复上述步骤,直到 n=1 时停止。计算 i 到 j 之间的整数中,循环节长度的最大值。由于n 是不小于1000 000的整数,所以用递归虽然很方便,但是容易超时,后来改为递推仍然超时。其实想想有的数会重复计算,因此可以用数组保存下来,也就是我们通常所说的打表方法。
注意:输出的整数 m 与 n ,不一定是 m<n,所以要做交换,使其满足条件。由于要求输出这两个整数,所以刚开始要保存下来。
另外请注意编译环境问题,UVa中不支持__int 64 类型,支持 long long 型,而在C++6.0中则恰恰相反。
View Code
1 #include<cstdio>
2 #include<iostream>
3 using namespace std;
4 #define MAX 1000005
5 int an[MAX];
6 int main()
7 {
8 int i,m,n,t,a,b;
9 an[1]=1;
10 an[2]=2;
11 for(i=3;i<MAX;i++)
12 {
13 long long k;
14 k=i;
15 int sum=0;
16 while(1)
17 {
18 if(k%2==1)
19 {
20 k=3*k+1;
21 sum++;
22 }
23 else{
24 sum++;
25 k=k/2;
26 }
27 if(k<i) //判断是否已经计算出
28 {
29 an[i]=sum+an[k];
30 break;
31 }
32 }
33 }
34 while(scanf("%d%d",&m,&n)!=EOF)
35 {
36 int max=0;
37 a=m;b=n;
38 if(m>n) { t=m;m=n;n=t; }
39 for(i=m;i<=n;i++)
40 if(max<an[i]) max=an[i];
41 printf("%d %d %d\n",a,b,max);
42 }
43 return 0;
44 }
2 #include<iostream>
3 using namespace std;
4 #define MAX 1000005
5 int an[MAX];
6 int main()
7 {
8 int i,m,n,t,a,b;
9 an[1]=1;
10 an[2]=2;
11 for(i=3;i<MAX;i++)
12 {
13 long long k;
14 k=i;
15 int sum=0;
16 while(1)
17 {
18 if(k%2==1)
19 {
20 k=3*k+1;
21 sum++;
22 }
23 else{
24 sum++;
25 k=k/2;
26 }
27 if(k<i) //判断是否已经计算出
28 {
29 an[i]=sum+an[k];
30 break;
31 }
32 }
33 }
34 while(scanf("%d%d",&m,&n)!=EOF)
35 {
36 int max=0;
37 a=m;b=n;
38 if(m>n) { t=m;m=n;n=t; }
39 for(i=m;i<=n;i++)
40 if(max<an[i]) max=an[i];
41 printf("%d %d %d\n",a,b,max);
42 }
43 return 0;
44 }