稳定的数字(贪心)(高精度)

稳定的数字

题目大意

定义把一个数变换一次得到的是它每一位乘起来的数。(原来的数一定要至少是二位的)
然后给你变换后的数,问你最小能变换成它的数是什么。

思路

首先不难想到是要把这个数质因数分解。
然后如果有大于 9 9 9 的质数就代表无法搞出来。

接着我们考虑是否要把一些质数合成成大一点的,使得数位数更少。
我们贪心一下,会发现从高位往低位,能合就尽可能的和。(因为这样不但位数会更少,而且剩下的不能和的数也会尽可能的小)

然后最后从 2 ∼ 9 2\sim9 29,按你弄出的次数输出每个数,然后就可以了。

吗?

显然要特判,因为他说原来的数至少是二位数,那如果给出的数是 0 0 0,答案就是 10 10 10,给出的是 1 1 1,答案就是 11 11 11,如果是 2 ∼ 9 2\sim9 29,答案就是 12 ∼ 19 12\sim 19 1219
前面两个特判,后面一个就是如果输出的数只有一位就在前面多输出一个 1 1 1

然后就好啦。
(然后显然要高精除)

代码

#include<cstdio>
#include<cstring>
#include<algorithm> 

using namespace std;

struct gj {
	int n;
	int a[10001];
}n;
int pn[11], nm;
char s[10001];

bool seechu(int x) {//高精除分解质因数
	int el = 0;
	for (int i = n.n; i >= 1; i--) {
		el *= 10;
		el += n.a[i];
		el %= x;
	}
	return !el;
}

void chu(int x) {
	int el = 0;
	for (int i = n.n; i >= 1; i--) {
		el *= 10;
		el += n.a[i];
		n.a[i] = el / x;
		el %= x;
	}
	while (!n.a[n.n]) n.n--;
}

int main() {
	scanf("%s", s + 1);
	n.n = strlen(s + 1);
	
	if (s[1] == '-') {//负数不行
		printf("There is no such number.");
		return 0;
	}
	
	for (int i = 1; i <= n.n; i++)
		n.a[n.n - i + 1] = s[i] - '0';
	
	if (n.n == 1 && n.a[1] == 0) {//特判 0,1
		printf("10");
		return 0;
	}
	if (n.n == 1 && n.a[1] == 1) {
		printf("11");
		return 0;
	}
	
	while (seechu(2)) {//分解质因数
		chu(2); pn[2]++; nm++;
	}
	while (seechu(3)) {
		chu(3); pn[3]++; nm++;
	}
	while (seechu(5)) {
		chu(5); pn[5]++; nm++;
	}
	while (seechu(7)) {
		chu(7); pn[7]++; nm++;
	}
	
	if (n.n > 1 || n.a[1] != 1) {//有 >9 的质数,无法乘出来
		printf("There is no such number.");
		return 0;
	}
	
	while (pn[3] >= 2) {//从大到小,能用就用
		pn[3] -= 2;
		pn[9]++;
		nm -= 1;
	}
	while (pn[2] >= 3) {
		pn[2] -= 3;
		pn[8]++;
		nm -= 2;
	}
	while (pn[2] && pn[3]) {
		pn[2]--; pn[3]--;
		pn[6]++;
		nm -= 1;
	}
	while (pn[2] >= 2) {
		pn[2] -= 2;
		pn[4]++;
		nm -= 1;
	}
	
	if (nm == 1) printf("1");//特判只有一位数,要补一个 1 使他成为二位数
	for (int i = 2; i <= 9; i++)
		while (pn[i]) {
			pn[i]--;
			putchar(i + '0');
		}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值