有一个算法为
1. input n2. print n
3. if n = 1 then STOP
4. if n is odd then
5. else
6. GOTO 2
生成的序列的长度称为n的cycle-length。
input:i和j(i和j都小于1000,000)
output:i和j之间所有数的cycle-length的最大值
Sample Input
1 10 100 200 201 210 900 1000
Sample Output
1 10 20 100 200 125 201 210 89 900 1000 174
解题思路:
申请一个堆,用来存储1~999999的cycle-length。对于每一对输入i和j,从小到大遍历,得到cycle-length后将结果存入堆中;计算时如果遇到了先前计算过的数,可以break当前算法的循环,直接在堆中查找剩余长度。
如果n是2的幂,那么可以直接推出cycle-length,例如n=16时,序列就为16,8,4,2,1;cycle-length = 5.
【我想也许存在更高效的算法,因为16之前的数要么为奇数5,要么为偶数32;而8之前不可能为奇数,只能是偶数16;造成这个差别的原因是16 - 1 = 15能被3整除,而8 - 1 = 7不能被3整除……而且程序结果证明,1到999999之间最大的cycle也只有五百多,所以猜测这个序列是很有规律的……】
代码:
#include <iostream>
using namespace std;
int arr[1000000];
int main()
{
int l = 1 ;
int t = 1 ;
while(l < 1000000)
{
arr[l] = t ;
l *= 2 ;
t ++ ;
}
unsigned int i,j ;
while(cin >> i)
{
cin >> j;
cout << i << ' ' << j << ' ' ;
if(i > j)
{
unsigned int tmp = i ;
i = j ;
j = tmp ;
}
int maxlength = 0 ;
for(unsigned int c = i ; c <= j ; c ++)
{
unsigned int tmp = c ;
int count = 0 ;
while(tmp)
{
if (tmp < 1000000 && arr[tmp])
{
count += arr[tmp] ;
break ;
}
if(tmp % 2)
tmp = tmp * 3 + 1 ;
else
tmp /= 2 ;
count ++ ;
}
arr[c] = count ;
if (count > maxlength)
{
maxlength = count ;
}
}
cout << maxlength << endl ;
}
return 0 ;
}
我的CT(code teacher)说,这个代码真难看~嗯,还要加油