我编写了一个程序来解决在线评判中的3n + 1问题(Collatz Conjecture)。我注意到了重要的问题,例如,第一个输入可能小于第二个输入,等等。
但在网上判断时,我总会得到错误答案的通知。你能帮我看看我犯错的地方吗?谢谢。
以下是我的计划。请注意,我使用数组来存储遍历数字的循环。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char const *argv[])
{
int maxcyc = 0;
int curcyc;
int i, min, max;
unsigned long n;
int *cach = (int *)malloc(1000000 * sizeof(int));
if (cach == NULL)
{
printf("Memory Allocation Error\n");
}
for (i = 0; i < 1000000; ++i)
{
cach[i] = 0;
}
if (scanf("%d %d", &min, &max) == 2)
{
printf("%d %d ", min, max);
if (min > max)
{
min = min ^ max;
max = max ^ min;
min = min ^ max;
}
for (i = min; i < max + 1; ++i)
{
curcyc = 1;
n = i;
while (n != 1)
{
if (n < 1000000 && cach[n])
{
curcyc = curcyc + cach[n] - 1;
break;
}
curcyc++;
if (n & 0x0001)
{
if (n >= ULONG_MAX / 3)
{
printf("%d overflow at step %d\n", i, curcyc);
}
n = 3 * n + 1;
}
else
{
n = n >> 1;
}
}
cach[i] = curcyc;
maxcyc = maxcyc > curcyc ? maxcyc : curcyc;
}
printf("%d\n", maxcyc);
}
free(cach);
return 0;
}
PS:有关此问题的详细说明和说明,请参阅http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=36
我已经通过将n的类型更改为unsigned long
来更新代码,并添加了if
语句以预期检查溢出超前3 * n + 1.但是此程序中仍然存在错误,没有通过判决。还需要帮助。感谢。
答案 0 :(得分:1)
将curcyc从0开始而不是1,并且不从缓存值中减去。因此,你的算法是错误的。
此外,在执行算法期间,n可能会溢出,具体取决于起始值。
答案 1 :(得分:1)
我对此工作有点自信。它产生的答案与我在高达100万的评论中提到的蛮力bc
程序相同(至少,一旦我修改了bc
程序来计算链中的值的数量,比过渡的数量)。它快达100万。当缓存在1000万和1亿时变得不那么有效时,它会变慢。
示例输出(使用-DPRODUCTION
编译的代码):
$ j=10; for i in 0 0 0 0 0 0 0; do j="$j$i"; ./collatz-so <<< "2 $j"; done
2 100 119
2 1000 179
2 10000 262
2 100000 351
2 1000000 525
2 10000000 686
2 100000000 950
$
示例输出,其代码已编译为debug:
$ ./collatz-so <<< '1 30'
1: 1
2: 2
3: 8
4: 3
5: 6
6: 9
7: 17
8: 4
9: 20
10: 7
11: 15
12: 10
13: 10
14: 18
15: 18
16: 5
17: 13
18: 21
19: 21
20: 8
21: 8
22: 16
23: 16
24: 11
25: 24
26: 11
27: 112
28: 19
29: 19
30: 19
1 30 112
$
代码:
#include <stdio.h>
#include <stdlib.h>
#if defined(PRODUCTION)
#define DEBUG 0
#else
#define DEBUG 1
#endif
static const int debug = DEBUG;
enum { CACHE_SIZE = 1000000 };
int main(void)
{
int maxcyc = 0;
int curcyc;
int i, min, max;
unsigned long n;
int *cache = (int *)calloc(CACHE_SIZE, sizeof(int));
if (cache == NULL)
{
printf("Memory Allocation Error\n");
return 1;
}
if (scanf("%d %d", &min, &max) == 2)
{
if (min > max)
{
min = min ^ max;
max = max ^ min;
min = min ^ max;
}
for (i = min; i < max + 1; ++i)
{
curcyc = 1;
n = i;
while (n != 1)
{
if (n < CACHE_SIZE && cache[n])
{
//printf("%lu: cache[%lu] = %d; c = %d\n", n, n, cache[n], curcyc);
curcyc += cache[n] - 1;
break;
}
curcyc++;
if (n & 0x0001)
n = 3 * n + 1;
else
n /= 2;
}
if (i < CACHE_SIZE)
{
cache[i] = curcyc;
//printf("cache[%d] = %d\n", i, curcyc);
}
if (debug)
printf("%4d: %4d\n", i, curcyc);
maxcyc = maxcyc > curcyc ? maxcyc : curcyc;
}
printf("%d %d %d\n", min, max, maxcyc);
}
free(cache);
return 0;
}