/*
丑数:
我们把只包含因子2、3和5的数称为丑数,求按照从小到大的顺序的第1500个丑数。例如6,8都是丑数,但14不是丑数
,因为它包含因此7.习惯上我们把1当做第一个丑数。
分析:
采用累除法,凡是能除得尽的都是丑数,模拟素数筛选法来做,对模拟的素数筛选法中,2,3,5
书上的方法:
创建数组保存已经找到的丑数,用空间换时间。
创建一个数组,里面的数字时排好序的丑数,每一个丑数都是前面的丑数乘以2,3,5
关键:如何确保里面的丑数是排好序的。
假设数组中已有部分排好序的丑数,把最大的丑数记为M。分析如何生成下一个丑数。
该丑数= 前面某个丑数*(2或3或5),首先把每个已有丑数*2,能得到若干个<=M的结果,而这些必定存在。
我们需要第一个大于M的结果,希望丑数是按从小到大顺序生成。
把得到的第一个乘以2后大于M的结果即为M2,同样乘以3或5,得到M3,M5.
下一个丑数 = min{M2,M3,M5}
对于乘以2而言,存在丑数T2,排在它之前的每个丑数乘以2得到的结果<已有最大丑数,在它之后的每个丑数*2
会太大。我们只需记录这个丑数的位置,同时每次生成新的丑数是,更新T2,对乘3和乘5而言,同样存在T3和T5。
输入:
输入包括一个整数N(1<=N<=1500)。
输出:
可能有多组测试数据,对于每组数据,
输出第N个丑数。
样例输入:
3
样例输出:
3
*/
/*
关键:
1 对于乘以2而言,存在丑数T2,排在它之前的每个丑数乘以2得到的结果<已有最大丑数,在它之后的每个丑数*2
会太大。我们只需记录这个丑数的位置,同时每次生成新的丑数是,更新T2,对乘3和乘5而言,同样存在T3和T5。
2 pMul2 = pMul3 = pMul5 = iUglyNumArr;//初始设定丑数数组中乘以2或3或5后,大于丑数数组中最大值的丑数指针为起始值
3 int iMin = min(*pMul2*2,*pMul3*3,*pMul5*5);//选定丑数
iUglyNumArr[iNextIndex] = iMin;//设定下一个丑数
while(*pMul2*2 <= iMin)//更新丑数数组*(2或3或5)大于当前丑数数组中最大值的丑数的位置
{
pMul2++;
}
*/
#include <stdio.h>
const int MAXSIZE = 1501;
int min(int num1,int num2,int num3)
{
int iMin = num1 < num2 ? num1 : num2;
iMin = iMin < num3 ? iMin : num3;
return iMin;
}
int getUglyNum(int n)
{
if(n < 0 || n > 1500)
{
return -1;
}
int iUglyNumArr[MAXSIZE];
iUglyNumArr[0] = 1;
int iNextIndex = 1;
int* pMul2,*pMul3,*pMul5;
pMul2 = pMul3 = pMul5 = iUglyNumArr;//初始设定丑数数组中乘以2或3或5后,大于丑数数组中最大值的丑数指针为起始值
while(iNextIndex < n)
{
int iMin = min(*pMul2*2,*pMul3*3,*pMul5*5);//选定丑数
iUglyNumArr[iNextIndex] = iMin;//设定下一个丑数
while(*pMul2*2 <= iMin)//更新丑数数组*(2或3或5)大于当前丑数数组中最大值的丑数的位置
{
pMul2++;
}
while(*pMul3*3 <= iMin)
{
pMul3++;
}
while(*pMul5*5 <= iMin)
{
pMul5++;
}
iNextIndex++;
}
return iUglyNumArr[n -1];
}
void process()
{
int n;
while(EOF != scanf("%d",&n))
{
if(n < 0 || n > 1500)
{
continue;
}
printf("%d\n",getUglyNum(n));
}
}
int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}