如果一个正整数最多只包含2,3,5,7这四种素因子,则称这个正整数为丑数。数列1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27就是前20个丑数。
丑数都是由2,3,5,7构成,也就是任意丑数都可以表示为DP[n]=2^a+3^b+5^c+7^d;
求出升序,那么我们只需要保证每次乘与2,3,5,7的因子后一直是最小(同时比前一项大即可)
举例一下
因为后面的丑数都是由前面得到,那么我们对4个因子标记是他*第几个丑数会是当前第n个丑数最小
方法一
#include <bits/stdc++.h>
using namespace std;
const int N = 6000;
int dp[N];
int main() {
int n2=1, n3=1, n5=1, n7 = 1; //表示因子各自从第几个丑数乘获得最小,一开始都是第一个
int a; int x = 1;
dp[1] = 1;
while (x < N) {
a = min(2 * dp[n2], min(3 * dp[n3], min(5 * dp[n5], 7 * dp[n7])));
if (a == 2 * dp[n2])n2++;
if (a == 3 * dp[n3])n3++;//n2,3,5,7各自分开,使他们都是从第一个丑数开始迭代增加,每使用过一次(自己乘后是丑数最小),自己的nx就加一下,表示下次会用下一个丑数取乘积
if (a == 5 * dp[n5])n5++;
if (a == 7 * dp[n7])n7++;
dp[++x] = a;//储存
}
int n;
while (cin >> n && n) {
cout << dp[n] << endl;
}
return 0;
}
因为我们只需要保证每次乘与2,3,5,7的因子后一直是最小(同时比前一项大即可),我们也可以选择遍历前面的丑数来乘,3,5,7获得最小
方法二
#include <bits/stdc++.h> using namespace std; const int N = 6000; long long dp[N]; int in[4] = { 2,3,5,7 };//表示4个因子 int main() { memset(dp, 0x3f3f3f3f, sizeof(dp)); //初始值dp[n]赋值极大,保证下面第一次存入dp[i]能存入 dp[1] = 1; for (int i = 2; i <= N; ++i)for (int j = i-1; j>=1; --j)for (int k = 3; k>=0; --k){ //j从i-1遍历,左移,只要dp[j]*7还小于dp[i],就可以退出,减少计算 if (dp[j] * in[k] > dp[i - 1])dp[i] = min(dp[i], dp[j] * in[k]); else break; } int n; while (cin >> n && n) { cout << dp[n] << endl; } return 0; }