题意:有一个长度为K的质数集S = {p1, p2, p3, ... , pk},一个整数被定义为humble number当且仅当这个数的因子都是S中的数,求第N个humble number。
解题思路:
- 用DP解决,设result[i]为第i个humble number,result[0] = 1,质数集保存在prime_set中。
- 已知result[k] 求 result[k+1]的过程如下:对质数集中的每一个质数prime_set[j],求最小的result[p]使得prime_set[j] * result[p] > result[k]。然后求所有这些比result[k]大的值中最小的一个,就是result[k+1]。在求解过程中可以用一个index[j]数组来保存使prime_set[j] * result[p] > result[k]的最小的p,这样下次搜索的时候可以直接从index[j]开始,削减了计算量。
- result[N]即为所求。
代码:
/*
ID: zc.rene1
LANG: C
PROG: humble
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
FILE *fin, *fout;
int K, N;
int i, j, p, temp, temp_min;
int *prime_set = NULL, *result = NULL, *index = NULL;
fin = fopen("humble.in", "r");
fout = fopen("humble.out", "w");
fscanf(fin, "%d %d", &K, &N);
prime_set = (int *)malloc(K*sizeof(int));
for (i=0; i<K; i++)
{
fscanf(fin, "%d", &prime_set[i]);
}
result = (int *)malloc((N+1)*sizeof(int));
index = (int *)malloc(N*sizeof(int));
memset(result, 0, (N+1)*sizeof(int));
memset(index, 0, (N+1)*sizeof(int));
result[0] = 1;
for (i=1; i<=N; i++)
{
for (j=0; j<K; j++)
{
for (p=index[j]; p<i; p++)
{
temp = prime_set[j] * result[p];
if ( temp > result[i-1])
{
index[j] = p;
break;
}
}
if (j == 0)
{
temp_min = temp;
}
else
{
if (temp < temp_min)
{
temp_min = temp;
}
}
}
result[i] = temp_min;
}
fprintf(fout, "%d\n", result[N]);
return 0;
}