UVa Problem Solution: 100 - The 3n+1 problem


I originally used the straight forward method and got a RT of 1.250s. I believe that if I were using Java, I would get a TL. Thus, I switch to the method of precomputing all the cycle-lengths in range (0, 1000000).

Let a l, a l-1, ..., a 1 donate the sequence generate by n = a l whose cycle-length is l. We can use the following recurrence to accelerate the precomputing process:

   
cycle-length (ai) = cycle-length (ai-1) + 1

Obviously,  we should follow a bottom-up manner to calculate cycle-lengths from a 1 = 1. Here, we call ai depends on ai-1 if ai-1 is the next element of ai in the generated sequence. In fact, there will be two numbers that depend on n if n % 3 == 1 and (n-1)/3 % 2 == 1. Thus, the dependences form a tree-like structure and we should keep track of all of them.
 
However, some numbers in the generated sequence is too large to keep the cycle-lengths of them in the cycle-length table. In the following code, I just throw them away and recalculate them every time when needed. A more elegant way is keeping them in a hash table to save the recalculating time.
 
Code:
  1. /*************************************************************************
  2.  * Copyright (C) 2008 by liukaipeng                                      *
  3.  * liukaipeng at gmail dot com                                           *
  4.  *************************************************************************/
  5. /* @JUDGE_ID 00000 100 C "The 3n+1 problem" */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <strings.h>
  10. #define MAX 1000000
  11. /*************************************************************************
  12.  * Queue (FIFO)                                                          *
  13.  * Note: No error check is performed.                                    *
  14.  *************************************************************************/
  15. #define QUEUESIZE MAX
  16. typedef size_t valuetype;
  17. typedef struct queue {
  18.   valuetype data[QUEUESIZE];
  19.   int head;
  20.   int tail;
  21.   int size;
  22. } queue;
  23. void initqueue(queue *q) {
  24.   q->head = 0;
  25.   q->tail = 0;
  26.   q->size = 0;
  27. }
  28. int emptyqueue(queue *q) {
  29.   return q->size == 0;
  30. }
  31. void enqueue(queue *q, valuetype v) {
  32.   q->data[q->tail++] = v;
  33.   q->tail %= QUEUESIZE;
  34.   q->size += 1;
  35. }
  36. valuetype dequeue(queue *q) {
  37.   valuetype v = q->data[q->head++];
  38.   q->head %= QUEUESIZE;
  39.   q->size -= 1;
  40.   return v;
  41. }
  42. /*************************************************************************/
  43. int len[MAX] = {0};
  44. queue q;
  45. void fill()
  46. {
  47.   initqueue(&q);
  48.   len[1] = 1;
  49.   enqueue(&q, 1);
  50.   for (; !emptyqueue(&q); ) {
  51.     int cur = dequeue(&q);
  52.     int pre;
  53.     /* find the previous elements in the cycle */
  54.     if (cur*2 < MAX) {
  55.       pre = cur*2;
  56.       len[pre] = len[cur] + 1;
  57.       enqueue(&q, pre);
  58.     }
  59.     if (cur % 3 == 1 && (cur-1)/3 % 2 == 1 && (cur-1)/3 != 1) {
  60.       pre = (cur-1)/3;
  61.       len[pre] = len[cur] + 1;
  62.       enqueue(&q, pre);
  63.     }
  64.   }
  65.   {
  66.     int i;
  67.     for (i = 3; i < MAX; ++i) {
  68.       if (len[i] == 0) {
  69.         unsigned int j;
  70.         int d;
  71.         for (j = i, d = 0; j >= MAX || len[j] == 0; ++d) {
  72.           if (j % 2 == 0)
  73.             j = j/2;
  74.           else
  75.             j = 3*j+1;
  76.         }
  77.         len[i] = len[j] + d;
  78.       }
  79.     }
  80.   }  
  81. }
  82. int main(int argc, char *argv[])
  83. {
  84. #ifndef ONLINE_JUDGE
  85.   char in[256];
  86.   char out[256];
  87.   strcpy(in, argv[0]);
  88.   strcat(in, ".in");
  89.   freopen(in, "r", stdin);
  90.   strcpy(out, argv[0]);
  91.   strcat(out, ".out");
  92.   freopen(out, "w", stdout);
  93. #endif
  94.   int i, j;
  95.   fill();
  96.   while (scanf("%d %d", &i, &j) != EOF) {
  97.     int max = 0;
  98.     printf("%d %d ", i, j);
  99.     if (i > j) {
  100.       i ^= j;
  101.       j ^= i;
  102.       i ^= j;
  103.     }
  104.     for (; i <= j; ++i)
  105.       if (len[i] > max) 
  106.         max = len[i];
  107.     printf("%d/n", max);
  108.   }
  109.   return 0;
  110. }


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值