题目:
Description
Input
Output
Sample Input
1 10 100 200 201 210 900 1000
Sample Output
1 10 20 100 200 125 201 210 89 900 1000 174
题目简述:
对于3n+1问题,22的结果是:22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 ,一共16个数
所以22的cycle length是16
现在,输入x,y,要求输出x和y之间所有数的cycle length的最大值。
我的第一个程序是,先记忆化搜索求出1到1000000的cycle length
然后用max型线段树,来减少查询时间。
代码:
#include<iostream> using namespace std; int num[1000000]; int max[4000000]; int init(long long k) { if (k<1000000 && num[k])return num[k]; int r; if (k % 2)r = init(k * 3 + 1) + 1; else r = init(k / 2) + 1; if (k < 1000000)num[k] = r; return r; } void build(int key, int low, int high) { if (low == high) { max[key] = num[low]; return; } int mid = (low + high) / 2; build(key * 2, low, mid); build(key * 2 + 1, mid + 1, high); max[key] = (max[key * 2] > max[key * 2 + 1]) ? max[key * 2] : max[key * 2 + 1]; } int query(int key, int low, int high, int x, int y) { if (x > y)return query(key, low, high, y, x); if (low == x && high == y)return max[key]; int mid = (low + high) / 2; if (mid < x)return query(key * 2 + 1, mid + 1, high, x, y); if (mid >= y)return query(key * 2, low, mid, x, y); int a = query(key * 2, low, mid, x, mid); int b = query(key * 2 + 1, mid + 1, high, mid + 1, y); return (a>b) ? a : b; } int main() { for (int i = 1; i < 1000000; i++)num[i] = 1 - (i>1); for (int i = 1; i < 1000000; i++)init(i); build(1, 1, 1000000); int x, y; while (scanf("%d%d", &x, &y) != -1)printf("%d %d %d\n", x, y, query(1, 1, 1000000, x, y)); return 0; }
最开始超时了,因为没有判断x和y谁大谁小,这个代码在query里面加了一行,就AC了。
然而我发现有个人的代码特别快,而且特别短,我就看了一下。
居然是!!不用记忆华搜索也不用线段树,根本连数组都没有出现!
于是我也试了一下这个方法。
代码:
#include<iostream> using namespace std; int l(int k) { if (k == 1)return 1; if (k % 2)return l(k * 3 + 1) + 1; return l(k / 2) + 1; } int maxs(int x, int y) { if (x > y)return maxs(y, x); int maxx = 0; for (int i = x; i <= y; i++)if (maxx < l(i))maxx = l(i); return maxx; } int main() { int x, y; while (scanf("%d%d", &x, &y) != -1)printf("%d %d %d\n", x, y, maxs(x,y)); return 0; }
果然很短,而且还是0ms。。。
关键还是要看给的数据。
在上面的init函数里面,我专门做了判断,判断参数k有没有超过1000000
实际上,我的k是long long的。
这是因为,运行init函数的时候就发现了,在计算1到1000000的cycle length的时候,会出现很大的数。
到底有多大我没有去追究,反正已经超过int了,所以我计算1到1000000的cycle length才会很慢。
题目已经说明了不会超过int,也就是说输入是有限制的。