POJ 1338 Ugly Number

 


官方题解如下:
{
我们在数组hum中计算出前n个丑数。为了实现起来更简单,我们把1也作为一个丑数,算法也要因此略微调整一下。

当我们已知前k个丑数,想得到第k+1个,我们可以这样做:
对于每个质数p 寻找最小的丑数h 使得 h * p 比上一个丑数大 取我们找到的 h * p 中最小的一个:它就是下一个丑数

为了使搜索更快,我们可以为每个质数维护一个索引“pindex”表示每个质数已经乘到了哪个丑数(即从之前的丑数里,
要得到最小的丑数,每个质数应该开始乘的位置索引),每次都从那里开始,而不是再从头再来。
}
根据上面的分析,可以使用一个数组a作为pindex,a[j]表示质数p[j]从已求的丑数集里开始乘的索引。
初始化时,每个质数从第一个丑数h[0]开始乘。
每次求下一个丑数h[i]时,首先根据上一个丑数h[i-1],检查a[i]是否需要更新。
如果p[j]*h[a[j]]已经小于上一个丑数h[i-1]了,那么当前素数p[j]的“应该开始乘的数在丑数集h里的索引”需要增加。
最后再去最小的p[j]*h[a[j]]。
#include <iostream> using namespace std; const int M = 1501; int h[M]={1}; int p[3]={2,3,5}; int a[3]={0}; int main() { int n = 0; int min_v; int i,j; for(i=1;i<M;i++) { for(j=0;j<3;j++) { if(h[a[j]]*p[j]<=h[i-1]) a[j]++; } min_v = 0x7fffffff; for(j=0;j<3;j++) { if(p[j]*h[a[j]]<min_v) min_v = p[j]*h[a[j]]; } h[i]=min_v; } scanf("%d",&n); while(n!=0) { printf("%d/n",h[n-1]); scanf("%d",&n); } }

 

你可能感兴趣的:(算法)