质数生成集
求第 k k k个丑数。
丑数 N N N的质因数只有 2 , 3 , 5 2,3,5 2,3,5。
我们知道任何一个丑数 N N N,都是小于 N N N的某一个丑数乘以 2 , 3 , 5 2,3,5 2,3,5生成的。因此,我们得到三个有序序列:
1 ∗ 2 , 2 ∗ 2 , 3 ∗ 2 , 4 ∗ 2 , 5 ∗ 2 , … 1 ∗ 3 , 2 ∗ 3 , 3 ∗ 3 , 4 ∗ 3 , 5 ∗ 3 , … 1 ∗ 5 , 2 ∗ 5 , 3 ∗ 5 , 4 ∗ 5 , 5 ∗ 5 , … 1*2,2*2,3*2,4*2,5*2,\ldots \\ 1*3,2*3,3*3,4*3,5*3,\ldots \\ 1*5,2*5,3*5,4*5,5*5,\ldots \\ 1∗2,2∗2,3∗2,4∗2,5∗2,…1∗3,2∗3,3∗3,4∗3,5∗3,…1∗5,2∗5,3∗5,4∗5,5∗5,…
本问题就相当于从一个合并三个虚构的有序序列即可。
设置三个指针 p 2 , p 3 , p 5 p2,p3,p5 p2,p3,p5分别指向各自序列的下标,依次取数即可。
#include <bits/stdc++.h>
using namespace std;
#define FR freopen("in.txt", "r", stdin)
#define FW freopen("out.txt", "w", stdout)
#define MAXT INT_MAX
typedef long long ll;
int dp[1600];
int main()
{
dp[1] = 1;
int p2 = 1;
int p3 = 1;
int p5 = 1;
for(int i = 2;i <= 1500;i++)
{
int val = min({dp[p2] * 2,dp[p3] * 3,dp[p5] * 5});
dp[i] = val;
if(val == dp[p2] * 2) p2++;
if(val == dp[p3] * 3) p3++;
if(val == dp[p5] * 5) p5++;
}
printf("The 1500'th ugly number is %d.",dp[1500]);
return 0;
}
此方法可以推广至任意素因子。