变幻数

变 幻 数 变幻数

题目链接:luogu P2821

题目

给定一个十进制正整数 n n n,它的递归变幻数定义如下:

  1. 如果 n n n的位数多于 1 1 1位(忽略前置的 0 0 0),将 n n n的各个位上的数相乘,乘积为 m m m。称 m m m n n n的子变幻数, n n n称为 m m m的父变幻数。求一个数的变幻数等于求其子变幻数。即求 n n n的变幻数等于求 m m m的变幻数。
  2. 如果 n n n的位数只有一位, n n n的变幻数即为它本身。 如求 679 679 679的变幻数过程为: 679 − > 378 ( = 6 ∗ 7 ∗ 9 ) − > 168 ( = 3 ∗ 7 ∗ 8 ) − > 48 ( = 1 ∗ 6 ∗ 8 ) − > 32 ( = 4 ∗ 8 ) − > 6 ( = 2 ∗ 3 ) 679 -> 378(=6*7*9) -> 168(=3*7*8) -> 48(=1*6*8) -> 32(=4*8) -> 6(=2*3) 679>378(=679)>168(=378)>48(=168)>32(=48)>6(=23),所以 679 679 679的变幻数为 6 6 6

现在的问题是给定一个子变幻数 k k k,问 k k k的父变幻数最小是多少? 如: k = 18 k=18 k=18,则 k k k的父变幻数可以是 29 29 29,也可以是 92 92 92。但最小为 29 29 29

输入

一个子变幻数 k ( k( k(位数小于 1000 ) 1000) 1000)

输出

k k k的最小父变幻数。 当不存在父变幻数时请输出 “ T h e r e   i s   n o   s u c h   n u m b e r ! ” “There\ is\ no\ such\ number!” There is no such number!,输出结果不含引号。

样例输入

48

样例输出

68

思路

这道题是一道贪心题。

题目告诉我们子变幻数就是父变幻数的各个位的乘积,那么就是说如果我们把子变幻数分解成一些大于 0 0 0小于 10 10 10的数,然后按各种方法排列起来的话,组成的数都是子变幻数的父变幻数。
由于要求最小的父变幻数,那么分解出来的数肯定是从小到大排列组成。而且,我们要让最后排列出来的数尽可能小,首先要让它的位数尽可能的少,那我们其实可以尽可能的先分出 9 9 9,接着是 8 8 8,再接着是 7 7 7,以此类推一直到 2 2 2(因为所有数 / 1 /1 /1都是本身,除了只会让位数变多),接着再从小到大排列(因为这样会让数字最小),就可以了。

有一点要注意的是要用高精除,因为子变幻数可以有1000位,父变幻数就更不用说了。

代码

#include<cstdio>
#include<cstring>

using namespace std;

int a[10], num[1001], k, an[1001];
char b[1001];

int main() {
	scanf("%s", &b);//读入
	for (int i = 0; i < strlen(b); i++) {
		num[++k] = b[i] - 48;//转换成数字
	}
	
	int i = 9;//初始化
	while (i >= 2) {//分解除每一个数字(以最优的方法)
		int now = 0;
		for (int j = 1; j <= k; j++) {//高精除
			now = now * 10 + num[j];
			an[j] = now / i;
			now %= i;
		}
		
		if (!now) {//判断能否整除
			int fr = 1;
			a[i]++;//可以被整除,计入答案
			while (!an[fr]) fr++;
			for (int j = fr; j <= k; j++)
				num[j - fr + 1] = an[j];
			k = k - fr + 1;
		}
		else i--;//不能整除
	}
	
	if (k > 1) printf("There is no such number!");//不存在父变幻数
		else {
			for (int i = 2; i <= 9; i++)
				for (int j = 1; j <= a[i]; j++)
					printf("%d", i);//输出答案
		}
	
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值