我正在尝试解决UVa在线评判的算法问题,但我被困在3n+1 problem上。我每次都看到正确的输出,但法官说这是一个错误的答案。为什么呢?
另外,如何优化此代码,以便1000000不需要很长时间?
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main(){
int a;
int b;
int cyclelength(int i);
while (scanf("%d %d\n",&a,&b)==2){
int max = 0;
if (b < a){
for (int i = b; i < a; i++){
if (cyclelength(i) > max)
max = cyclelength(i);
}
}
else
{
for (int i = a; i < b; i++){
if (cyclelength(i) > max)
max = cyclelength(i);
}
}
cout << a << " " << b << " " << max << endl;
}
}
int cyclelength(int i){
if(i==1)
return 1;
if(!(i%2))
return cyclelength(i/2)+1;
else
return cyclelength(3*i+1)+1;
}
答案 0 :(得分:0)
您提交的内容不正确,因为您没有在a
到b
范围内进行迭代。
问题陈述如下:
对于每对输入整数 i 和 j ,您应输出 i , j ,并且最大值 i 和 j 之间和之间的整数的循环长度。
您的代码循环
for (int i = b; i < a; i++)
和
for (int i = a; i < b; i++)
因此在前一种情况下省略a
,在后一种情况下省略b
。
您应该将循环更改为
for (int i = b; i <= a; i++)
和
for (int i = a; i <= b; i++)
您可以memoizing cyclelength
的结果稍微加快您的代码速度。这使您可以查找以前计算的值,而不是花时间再次计算它们。
以下是cyclelength
的备忘版本:
#include <map>
using namespace std;
map<long long, int> memo;
int cyclelength(long long i) {
if (i == 1) {
return 1;
}
if (memo.count(i) == 1) {
return memo[i];
}
if (i%2 == 0) {
return memo[i] = 1 + cyclelength(i/2);
} else {
return memo[i] = 1 + cyclelength(3*i + 1);
}
}
unordered_map
会更快,但UVA判断为#include <unordered_map>
返回了编译错误。
请注意,我的cyclelength
版本采用long long
参数。这让我可以计算cyclelength(999999)
,如果你将自己限制在32位整数值,最终会因重复的3n + 1操作而导致整数溢出。问题陈述承诺“没有操作溢出32位整数”,如果只使用int
值,则可以接受提交,但如果要计算{{1,则必须使用更大的整数类型对于范围[1,1000000)中的值。