丑数(HDU)固定公因子型(DP)

如果一个正整数最多只包含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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值