稳定的数字
题目大意
定义把一个数变换一次得到的是它每一位乘起来的数。(原来的数一定要至少是二位的)
然后给你变换后的数,问你最小能变换成它的数是什么。
思路
首先不难想到是要把这个数质因数分解。
然后如果有大于
9
9
9 的质数就代表无法搞出来。
接着我们考虑是否要把一些质数合成成大一点的,使得数位数更少。
我们贪心一下,会发现从高位往低位,能合就尽可能的和。(因为这样不但位数会更少,而且剩下的不能和的数也会尽可能的小)
然后最后从 2 ∼ 9 2\sim9 2∼9,按你弄出的次数输出每个数,然后就可以了。
吗?
显然要特判,因为他说原来的数至少是二位数,那如果给出的数是
0
0
0,答案就是
10
10
10,给出的是
1
1
1,答案就是
11
11
11,如果是
2
∼
9
2\sim9
2∼9,答案就是
12
∼
19
12\sim 19
12∼19。
前面两个特判,后面一个就是如果输出的数只有一位就在前面多输出一个
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;
}