01 void solve()
02 {
03 long i;
04 long c;
05 for(i = 2,c = 0;i <= LONG_MAX;i ++)
06 {
07 if(check(i))
08 c ++;
09 if(c == N)
10 {
11 printf("%ld\n",i);
12 break;
13 }
14 }
15 }
02 {
03 long i;
04 long c;
05 for(i = 2,c = 0;i <= LONG_MAX;i ++)
06 {
07 if(check(i))
08 c ++;
09 if(c == N)
10 {
11 printf("%ld\n",i);
12 break;
13 }
14 }
15 }
check(int i)函数用于检查i是否可以由输入文件中的质数构成。
这个算法很悲催地超时了,仅仅过了三个点,因为题目中humble number的上限是LONG_MAX。
然后想到DP方法,用布尔数组表示某个数是否是Humble Number,如果是,那么它乘上一个质数也是Humble number,但是,由于空间只有16M,这个算法所需空间估计要几百M,DP被迫放弃。
最后忍不住看了题解,题解给的方法也很直白:直接按顺序构造Humble number.
Once we have the first k humble numbers and want to compute the k+1st, we do the following:
for each prime p
find the minimum humble number h
such that h * p is bigger than the last humble number.
take the smallest h * p found: that's the next humble number.
01 #include <stdio.h>
02 #include <stdlib.h>
03 #include <limits.h>
04
05 void solve();
06
07 long prime[101];
08 long pos[101]; //用于加快计算下一个Humble number的速度,非常巧妙
09 long humble[100001];
10 long N,K;
11
12 void solve();
13
14 int main()
15 {
16 long i;
17 freopen("humble.in","r",stdin);
18 freopen("humble.out","w",stdout);
19 scanf("%ld%ld",&K,&N);
20 for(i = 0;i < K;i ++)
21 scanf("%ld",&prime[i]);
22 solve();
23 fclose(stdout);
24 fclose(stdin);
25 return 0;
26 }
27
28 void solve()
29 {
30 long i;
31 long min,minp;
32 long count = 0;
33 humble[count ++] = 1; //把1看作第0个Humble number,便于下面的计算
34 for(i = 0;i < K;i ++)
35 pos[i] = 0;
36 while(count <= N)
37 {
38 min = LONG_MAX;
39 for(i = 0;i < K;i ++)
40 {
41 while(prime[i] * humble[pos[i]] <= humble[count - 1])
42 pos[i] ++;
43 //神奇的pos数组
44 if(prime[i] * humble[pos[i]] < min)
45 {
46 min = prime[i] * humble[pos[i]];
47 minp = i;
48 }
49 }
50 humble[count ++] = min;
51 pos[minp] ++; //这句不是必须的
52 }
53 printf("%ld\n",humble[N]);
54 }
02 #include <stdlib.h>
03 #include <limits.h>
04
05 void solve();
06
07 long prime[101];
08 long pos[101]; //用于加快计算下一个Humble number的速度,非常巧妙
09 long humble[100001];
10 long N,K;
11
12 void solve();
13
14 int main()
15 {
16 long i;
17 freopen("humble.in","r",stdin);
18 freopen("humble.out","w",stdout);
19 scanf("%ld%ld",&K,&N);
20 for(i = 0;i < K;i ++)
21 scanf("%ld",&prime[i]);
22 solve();
23 fclose(stdout);
24 fclose(stdin);
25 return 0;
26 }
27
28 void solve()
29 {
30 long i;
31 long min,minp;
32 long count = 0;
33 humble[count ++] = 1; //把1看作第0个Humble number,便于下面的计算
34 for(i = 0;i < K;i ++)
35 pos[i] = 0;
36 while(count <= N)
37 {
38 min = LONG_MAX;
39 for(i = 0;i < K;i ++)
40 {
41 while(prime[i] * humble[pos[i]] <= humble[count - 1])
42 pos[i] ++;
43 //神奇的pos数组
44 if(prime[i] * humble[pos[i]] < min)
45 {
46 min = prime[i] * humble[pos[i]];
47 minp = i;
48 }
49 }
50 humble[count ++] = min;
51 pos[minp] ++; //这句不是必须的
52 }
53 printf("%ld\n",humble[N]);
54 }
真感叹pos数组的奇妙啊。pos[i]表示prime[i] * 某个humble数恰好大于前一个Humble数时这个humble数的位置。由于humble数组是递增的,因此可以大大节约时间,不需要每次都从第0个humble数开始搜索。
No comments:
Post a Comment