免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 9211 | 回复: 27
打印 上一主题 下一主题

[算法] 一个算法题,应该有很多种方法可以得到结果 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-05-07 10:18 |只看该作者 |倒序浏览
求第1500个只有2,3,5因子的数   
数是从小到大排列   
如:第一个数是1,1=2^0*3^0*5^0


结果应该如下:
1
2
3
4
5
6
8
9
10
12
15
16
18
...........
...........
800000000
805306368
806215680
810000000
816293376
819200000
820125000
829440000
838860800
839808000
843750000
849346560
850305600
854296875
859963392

第1500个值是859963392

我想出了两种方法,运行时间都在10毫秒以内,稍后再贴上来。
这题的方法很多,大家有什么好的想法也请贴上来,不过如果运行时间超过10秒的就算了吧,没有太多讨论的价值。

论坛徽章:
0
2 [报告]
发表于 2006-05-07 10:26 |只看该作者
楼上是怎么知道执行时间和站用内存的?

论坛徽章:
0
3 [报告]
发表于 2006-05-07 10:35 |只看该作者
原帖由 1jjk 于 2006-5-7 10:26 发表
楼上是怎么知道执行时间和站用内存的?

1、如果以N表示最后的结果值的话,那么可以得到O(log(N))的时间和空间占用,这个是对算法的分析得到的
2、实际的执行时间,可以用time ./a.out得到吧

论坛徽章:
0
4 [报告]
发表于 2006-05-09 10:54 |只看该作者
动态编程,设已经求出一个初始序列,用 2 乘之能得到 含 2^x3^y5^z 形式的元素(x>0);用 3 乘其中不含 2 的元素能得到 3^y5^z 形式的元素(y>0);用 5 乘其中 5 的方幂能到 5^z 形式的元素(z>0)。只要处理好放入的次序就行了,也就是3个序列的比较。

论坛徽章:
0
5 [报告]
发表于 2006-05-09 11:51 |只看该作者

  1. #include <stdio.h>

  2. #define N 1500

  3. unsigned long s[N];

  4. int
  5. main ()
  6. {

  7.         int now, idx2, idx3, i;
  8.         unsigned long val2, val3, val5;

  9.         s[0]=1;
  10.         now = 0;
  11.         val2=1; val3=1; val5=1;
  12.         idx2=0; idx3=0;


  13.         while (now < N-1) {
  14.                 if (val2 <= val3 && val2 <= val5) {
  15.                         if (val2>s[now])
  16.                                 s[++now]=val2;
  17.                         val2 = 2*s[idx2++];
  18.                 } else if (val3 <= val5) {
  19.                         if (val3>s[now])
  20.                                 s[++now]=val3;
  21.                         while (s[idx3++] % 2 == 0);
  22.                                 val3 = 3*s[idx3-1];
  23.                 } else {
  24.                         if (val5 >s[now])
  25.                                 s[++now]=val5;
  26.                         val5*=5;
  27.                 }
  28.         }

  29.                 printf("%u\n", s[1499]);
  30. }
复制代码


这个是 O(N) 的,在我的机器上要 30 毫秒

859963392

real        0m060s
user        0m0.030s
sys        0m0.040s


O(log N) 的没想出来。

[ 本帖最后由 win_hate 于 2006-5-9 13:58 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-05-09 13:17 |只看该作者
说一下我想到的两种方法:
(1)设C表示一个整数, N表示不超过C的只含有因子2,3,5的数的个数, 我们取足够大的C,使N>=1500, 把这N个数列出来,然后从小到大排序, 取第1500个就得到结果了.问题是要取多大的C才行呢?
通过对和的估计,可以得到C<= exp(三次根号(6*log2*log3*log5*N));取N=1500, 得到C<=4650268755.0;于是得到:
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <math.h>
  5. using namespace std;

  6. int main()
  7. {
  8.     vector<long long> result;
  9.     double max = 4650268755.0;
  10.     int i, j, k, idx = 0;
  11.     for(i=0; i<=log(max)/log(2.0); i++)
  12.         for(j=0; j<=log(max/pow(2.0,i))/log(3.0); j++)
  13.             for(k=0; k<=log(max/pow(2.0,i)/pow(3.0,j))/log(5.0); k++)
  14.                 result.push_back((long long)(pow(2.0, i) * pow(3.0, j) * pow(5.0, k)));
  15.     sort(result.begin(), result.end());
  16.     cout << result[1499] << endl;
  17. }
复制代码

[ 本帖最后由 yzc2002 于 2006-5-9 14:56 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2006-05-09 13:35 |只看该作者
1=n^0(n!=0)成立,按照lz的理论,1有任意多个因子
同样的,2,3,...都有1这个因子,所以,2,3,...都有任意多个因子
那么何来第1500个只有2,3,5因子的数?
因数和乘积紧密相关,所以,我们可以说1有因子2^0,3^0和5^0
但是,不论2^0,3^0还是5^0,它们都是1

或者这么说,什么是素数?只有1和它本身两个因子
那么如果1有2,3,5因子,素数岂不有2,3,5和它本身为因子
了,这与素数本身的定义已经相悖了。

搞不懂题目,实在不懂,请lz再详细说说^_^

论坛徽章:
0
8 [报告]
发表于 2006-05-09 13:35 |只看该作者
(2)第二种方法是通过递归的思想
设前n-1个数为A1,A2, ... ,An-1, 则下一个数An有三种情况:
1、k=(An-1, An) > 1 (这里(An-1, An)表示这两个数的最大公约数),则除以最大公约数后得到两个数B1, B2,这两个数也必定只含有因子2、3、5,所以它们在A1, A2 ... An-1中, 且必定相邻(否则设有B1<C<B2,则k*B1 < k*C < k*B2, 则An<= k*C<k*B2=An,矛盾)。所以把所有的Ak/Ak-1组成一个列表,则使An-1*Ak/Ak-1为整数的最小的值就是An。所以这里要用一个list,把所有的Ak/Ak-1存起来并按从小到大排序
2、An-1与An互素,若An-1含有2、3、5中两个因子,则An只有一个因子,设为k,即An=K的整数次方,显然An=k^([以k为底的An-1的对数]+1)
3、仍是互素,但An-1只含有一个因子,则An含有两个因子,设An=k^l*t^m, 则l从0开始遍历,由2可以直接得到m的值,得到最小的结果
以上的2、3情况下,得到的结果需要加入到list中,1的情况不需要
得到的程序比较麻烦:
  1. #include <stdio.h>
  2. #include <memory.h>
  3. #include <malloc.h>
  4. #include <stdlib.h>
  5. #ifdef WIN32
  6. typedef __int64 int64;
  7. #else
  8. typedef long long int64;
  9. #endif

  10. int base[] = {2, 3, 5};
  11. #define NUM  3
  12. int64 get_val(int *val_ary)
  13. {
  14.     int i, j;
  15.     int64 val = 1;
  16.     for(i=0; i < NUM; i++) {
  17.         if(val_ary[i] > 0)
  18.             for(j = 0; j < val_ary[i]; j++) val *= base[i];
  19.         else
  20.             for(j = 0; j > val_ary[i]; j--) val /= base[i];
  21.     }
  22.     return val;
  23. }
  24. void calc_next1(int *val_ary, int flag, int *val_next)
  25. {
  26.     int i, val = (int)get_val(val_ary);
  27.     for(i=0; i<NUM; i++) val_next[i] = 0;
  28.     for(i=0; val > 0; i++) val /= base[flag];
  29.     val_next[flag] = i;
  30. }
  31. void calc_next2(int *val_ary, int flag, int *val_next)
  32. {
  33.      int i = (flag + 1) % 3, j = (flag + 2) % 3, k, min = 0x7fffffff;
  34.      int tmp_val[NUM], val = (int)get_val(val_ary), max_k, val1;
  35.      calc_next1(val_ary, i, tmp_val);
  36.      max_k = tmp_val[i];
  37.      for(k=0; k <= max_k; k++) {
  38.          tmp_val[i] = val_ary[i] - k;
  39.          tmp_val[j] = 0;
  40.          tmp_val[flag] = val_ary[flag];
  41.          calc_next1(tmp_val, j, tmp_val);
  42.          tmp_val[i] = k;
  43.          tmp_val[flag] = 0;
  44.          while((val1 = (int)get_val(tmp_val)) < val) tmp_val[j]++;
  45.          if(min > val1) {
  46.              min = val1;
  47.              memcpy(val_next, tmp_val, sizeof(tmp_val));
  48.          }
  49.      }
  50. }

  51. struct node
  52. {
  53.     int *val_ary, *val_next;
  54.     struct node *next;
  55. };

  56. struct node *head;

  57. int cmp(struct node *p_node1, struct node *p_node2)
  58. {
  59.     int ary1[NUM], ary2[NUM];
  60.     int i, min;
  61.     int64 ret;
  62.     for(i=0; i < NUM; i++) {
  63.         ary1[i] = p_node1->val_next[i] + p_node2->val_ary[i];
  64.         ary2[i] = p_node1->val_ary[i] + p_node2->val_next[i];
  65.     }
  66.     for(i=0; i < NUM; i++) {
  67.         min = ary1[i] > ary2[i] ? ary2[i] : ary1[i];
  68.         ary1[i] -= min;
  69.         ary2[i] -= min;
  70.     }
  71.     ret = get_val(ary1) - get_val(ary2);
  72.     if(ret > 0) return 1;
  73.     else if(ret == 0) return 0;
  74.     else return -1;
  75. }

  76. void insert(struct node *p_node)
  77. {
  78.     struct node *ptr, **pre_ptr;
  79.     for(pre_ptr = &head, ptr=head; ptr != NULL && cmp(ptr, p_node) < 0 ; pre_ptr = &ptr->next, ptr = ptr->next)
  80.         ;
  81.     if(ptr != NULL && cmp(ptr, p_node) == 0) {
  82.         free(p_node->val_ary);
  83.         free(p_node->val_next);
  84.         free(p_node);
  85.     }
  86.     else{
  87.         *pre_ptr = p_node;
  88.         p_node->next = ptr;
  89.     }
  90. }
  91. void  free_list()
  92. {
  93.     struct node *ptr, *ptr1;
  94.     for(ptr=head; ptr!= NULL; ptr = ptr1)
  95.     {
  96.         ptr1 = ptr->next;
  97.         free(ptr->val_ary);
  98.         free(ptr->val_next);
  99.         free(ptr);
  100.     }
  101.     head = NULL;
  102. }
  103. void  disp()
  104. {
  105.     struct node *ptr;
  106.     for(ptr = head; ptr != NULL; ptr = ptr->next) {
  107.         printf("val1(%d, %d, %d)\n", ptr->val_ary[0], ptr->val_ary[1], ptr->val_ary[2]);
  108.         printf("val2(%d, %d, %d)\n", ptr->val_next[0], ptr->val_next[1], ptr->val_next[2]);
  109.     }
  110. }
  111. void  calc_next3(int *val_ary, int *val_next)
  112. {
  113.     struct node *ptr;
  114.     int i, flag = 0;
  115.     for(ptr = head; ptr != NULL && flag == 0; ptr = ptr->next) {
  116.         flag = 1;
  117.         for(i=0; i < NUM; i++) {
  118.             if( ptr->val_next[i] + val_ary[i] >= ptr->val_ary[i] ) {
  119.                 val_next[i] = ptr->val_next[i] + val_ary[i] - ptr->val_ary[i];
  120.             }
  121.             else {
  122.                 flag = 0;
  123.                 break;
  124.             }
  125.         }
  126.     }
  127. }
  128. void calc_next(int *val_ary, int *val_next)
  129. {
  130.     int mod = 0, flag1 = 0, flag2 = 0;
  131.     int i, tmp_val[NUM];
  132.     struct node *ptr;
  133.     for(i = 0; i < NUM; i++) {
  134.         if(val_ary[i] == 0) {
  135.             mod += 1; flag1=i;
  136.         }
  137.         else
  138.             flag2 = i;
  139.     }
  140.     switch(mod) {
  141.     case 0:
  142.         calc_next3(val_ary, val_next);
  143.         return;
  144.     case 1:
  145.         calc_next1(val_ary, flag1, tmp_val);
  146.         calc_next3(val_ary, val_next);
  147.         if(get_val(val_next) > get_val(tmp_val)) {
  148.             for(i = 0; i < NUM; i++) val_next[i] = tmp_val[i];
  149.             break;
  150.         }
  151.         return;
  152.     case 2:
  153.         calc_next2(val_ary, flag2, tmp_val);
  154.         calc_next3(val_ary, val_next);
  155.         if(get_val(val_next) > get_val(tmp_val)) {
  156.             for(i = 0; i < NUM; i++) val_next[i] = tmp_val[i];
  157.             break;
  158.         }
  159.         return;
  160.     case 3:
  161.         val_next[0] = 1;
  162.         val_next[1] = 0;
  163.         val_next[2] = 0;
  164.         break;
  165.     }

  166.     ptr = (struct node *)malloc(sizeof(struct node));
  167.     ptr->val_ary = (int *)malloc(sizeof(int) * NUM);
  168.     memcpy(ptr->val_ary, val_ary, sizeof(int) * NUM);
  169.     ptr->val_next = (int *)malloc(sizeof(int) * NUM);
  170.     memcpy(ptr->val_next, val_next, sizeof(int) * NUM);
  171.     ptr->next = NULL;
  172.     insert(ptr);
  173. }
  174. int main(int argc, char *argv[])
  175. {
  176.     int i;
  177.     int val_ary[NUM], val_next[NUM];
  178.     for(i = 0; i < NUM; i++) val_ary[i] = 0;
  179.     printf("1\n");
  180.     for(i = 1; i < atoi(argv[1]); i++) {
  181.         calc_next(val_ary, val_next);
  182.         printf("%d\n", get_val(val_next));
  183.         memcpy(val_ary, val_next, sizeof(val_ary));
  184.     }
  185.     free_list();
  186. }
复制代码

论坛徽章:
0
9 [报告]
发表于 2006-05-09 13:37 |只看该作者
原帖由 picktracy 于 2006-5-9 13:35 发表
1=n^0(n!=0)成立,按照lz的理论,1有任意多个因子
同样的,2,3,...都有1这个因子,所以,2,3,...都有任意多个因子
那么何来第1500个只有2,3,5因子的数?
因数和乘积紧密相关,所以,我们可以说1有因子2^0, ...

1是个特例,这里含有因子2、3、5是指形如2^i*3^j*5^k的数,其中0<= i, j, k

论坛徽章:
0
10 [报告]
发表于 2006-05-09 13:45 |只看该作者
原帖由 yzc2002 于 2006-5-9 13:37 发表

1是个特例,这里含有因子2、3、5是指形如2^i*3^j*5^k的数,其中0<= i, j, k


我还以为lz说的因子是通常意义上的因子,害我想的头发都掉了几根
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP