Description
定义一种操作,经过该操作,可以得到一个数中所有数字的乘积(原数至少要是个两位数)。比如679经过一次操作可以得到378。 你的任务读入一个数,计算经过一次操作得到它的最小的数是多少。
Input
仅一行,表示一个十进制数。数的长度可能到达1000位。
Output
经过一次操作可以得到这个数的最小的数。如果没有这样的数,输出“There is no such number.”(不包括引号)
Sample Input
输入1:
0
输入2:
18
输入3:
51
Sample Output
输出1:
10
输出2:
29
输出3:
There is no such number.
解题思路:这道题目数字虽然比较大0≤这个十进制数<101001,至多有1000位,但是我们还是可以做的,因为它求的是原来最小符合的数,然后我们知道这个运算的结果是这个数中所有数字的乘积,我们以此知道要分解质因数,又因为每一位数都是要小于10的,所以只能用10以内的质数来分解,如果最后剩下一个不是1的话就说明无解,因为要最小的数,所以要让它数位少,数字小,我们以此知道要让它后面的数字要尽量大,这样的话它的位数就会变少了,它的前面几位就会小,如果这个数是一位数的话,要在这个数的前面加上1就变成两位数,变成符合题目要求的数了。
代码如下:(仅供参考,请不要copy)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define u(i,x,y) for(int i=x;i<=y;i++)
#define d(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
char n[1001];
int s[1001],f[8],ans[1000],tot=0;
int cmp(const int &a,const int &b)
{
return a<b;
}
int work(int x)
{
int temp[1001],k=0;
temp[0]=s[0];
d(i,s[0],1)
{
int dd=(k*10+s[i]);
temp[i]=dd/x;
k=dd % x;
}
while(temp[temp[0]]==0) temp[0]--;
if(k==0)
{
for(int i=1;i<=temp[0];i++) s[i]=temp[i];
s[0]=temp[0];f[x]++;
return 1;
}
else return 0;
}
int main()
{
scanf("%s",n);
int len=strlen(n);
d(i,len+1,1) n[i]=n[i-1];
u(i,1,len) s[i]=int(n[len+1-i]-48);
s[0]=len;
if(s[0]==1) {printf("1%d",s[1]);return 0;}
while(work(2)) work(2);
while(work(3)) work(3);
while(work(5)) work(5);
while(work(7)) work(7);
if(s[0]>1) {printf("There is no such number.\n");return 0;}
int dui2=0,dui3=0;
dui2=f[2]/3;dui3=f[3]/2;
u(i,1,dui2) ans[++tot]=2*2*2;
u(i,1,dui3) ans[++tot]=3*3;
u(i,1,f[5]) ans[++tot]=5;
u(i,1,f[7]) ans[++tot]=7;
f[2]=f[2]%3;f[3]=f[3]%2;
if(!f[2])
if(f[3])
ans[++tot]=3;
if(f[2]==1)
{
if(f[3])
{
ans[++tot]=6;
}
else ans[++tot]=2;
}
if(f[2]==2)
{
if(f[3])
{
ans[++tot]=2;
ans[++tot]=6;
}
else ans[++tot]=4;
}
sort(ans+1,ans+tot+1,cmp);
u(i,1,tot) printf("%d",ans[i]);
printf("\n");
return 0;
}