humble number——二分查找与哈希表拉链法

Humble Numbers丑数

对于一给定的素数集合 S = {p1, p2, ..., pK}, 来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。注意:我们不认为1 是一个丑数。

你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。

PROGRAM NAME: humble

INPUT FORMAT

第 1 行:

二个被空间分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.

第 2 行:  

K 个被空间分开的整数:集合S的元素

SAMPLE INPUT (file humble.in)
4 19
2 3 5 7

OUTPUT FORMAT
单独的一行,写上对于输入的S的第N个丑数。

SAMPLE OUTPUT (file humble.out)
27

 

转移方程:f[i]=min{f[k]*a[j]}  1<=k<i,1<=j<=n

即用给定的素数乘以已经生成的丑数得到的积中最小的,时间复杂度为O(n*m),太低效。

优化:s[j]代表素数a[j]乘到的丑数位置,这样转移方程就变为了:

f[i]=min{f[s[j]]*a[j]} 1<=j<=n

时间复杂度为O(n)。

还有一个问题:判重。如果最小值出现过,则跳过,继续找其他里面的最小值,主要可以用

哈希表以及二分查找两种方法。能用二分查找是因为f[i]数组是有序的,如果无序就不能用了。

二分查找判重:

 

 

 

代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 int s[101],a[101],k,n;
5 long f[100001],min;
6
7 int check(long x,int low,int high)
8 {
9 int i,j,middle;
10 i=low;j=high;
11 while(i<=j)
12 {
13 middle=(i+j)/2;
14 if(f[middle]==x)return 1;
15 else
16 {
17 if(f[middle]<x)i=middle+1;
18 else j=middle-1;
19 }
20 }
21 return 0;
22 }
23
24 int main(){
25 FILE *in,*out;
26 in=fopen("input6.txt","r");
27 out=fopen("output.txt","w");
28 fscanf(in,"%d%d",&n,&k);
29 int i,j,x,j1;
30 for(i=1;i<=n;i++)
31 {
32 fscanf(in,"%d",&a[i]);
33 s[i]=1;
34 }
35
36 f[1]=1;
37 for(i=2;i<=k+1;i++)
38 {
39 min=2000000000;
40 for(j=1;j<=n;j++ )
41 if(min>f[s[j]]*a[j])
42 {
43 if(check(f[s[j]]*a[j],2,i-1))
44 {
45 s[j]++;
46 j--;
47 }
48 else
49 {
50 min=f[s[j]]*a[j];
51 x=j;
52 }
53 }
54 f[i]=min;s[x]++;
55 }
56
57 fprintf(out,"%ld\n",f[k+1]);
58 fclose(in);fclose(out);
59 return 0;
60 }

哈希表(拉链法,注意红色的代码):

 

代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<malloc.h>
5 int s[101],a[101],k,n;
6 int f[100001],min;
7 struct lis
8 {
9 int num;
10 struct lis *next;
11 }list[20000];
12
13 int check(int x)
14 {
15 int c;
16 c=x%20000;
17 struct lis *p;
18 if(x==list[c].num)return 1;
19 p=list[c].next;
20 while(p!=NULL)
21 {
22 if(x==p->num)return 1;
23 p=p->next;
24 }
25 return 0;
26
27 }
28
29 int main(){
30 FILE *in,*out;
31 in=fopen("input6.txt","r");
32 out=fopen("output.txt","w");
33 fscanf(in,"%d%d",&n,&k);
34 int i,j,x,j1,c;
35 for(i=1;i<=n;i++)
36 {
37 fscanf(in,"%d",&a[i]);
38 s[i]=1;
39 }
40 for(i=0;i<2000;i++)
41 {
42 list[i].num=0;
43 list[i].next=NULL;
44 }
45
46 f[1]=1;
47 for(i=2;i<=k+1;i++)
48 {
49 min=2000000000;
50 for(j=1;j<=n;j++ )
51 if(min>f[s[j]]*a[j])
52 {
53 if(check(f[s[j]]*a[j]))
54 {
55 s[j]++;
56 j--;
57 }
58 else
59 {
60 min=f[s[j]]*a[j];
61 x=j;
62 }
63 }
64 f[i]=min;
65 s[x]++;
66 c=min%20000;
67 if(list[c].num==0)list[c].num=min;
68 else
69 {
70 struct lis *p;
71 p=(struct lis *)malloc(sizeof(struct lis));
72 p->num=min;
73 p->next=list[c].next;
74 list[c].next=p;
75
76 }
77
78 }
79
80 fprintf(out,"%d\n",f[k+1]);
81 fclose(in);fclose(out);
82 return 0;
83 }

 

 

 

posted @ 2010-08-06 12:06  Danty  阅读(731)  评论(0编辑  收藏  举报