简要题意
每行输入一组数据,包含一个数,试求一个数,使该数满足其各位的乘积等于输入的数且该数的值在所有满足以上条件的数中最小. 输入以单独的一个-1结束. 保证输入的数的位数不超过1000位,输出的数的位数不超过3000位. 如果对于某一组数据,没有任何满足条件的数存在,则输出“There is no such number.”
题目分析
不妨首先假设这个数存在. 思考:在什么情况下所求数最小呢?可以发现,首先要数位最小,其次要数位的数由高数位到低数位升序排列. 分析可知我们可以使用贪心. 那么我们就可以得到以下的贪心思路:
由9到2进行for循环,
若输入的数能被k个i整除,
则将这k个i放到输出队列的末尾,并输入除以k*i;
当输入只剩下一位时,就可以按顺序输出结果了.
接下来我们考虑数不存在的情况,可以发现,如果输入仍然大于9且不能被2~9的任何一个数整除,则该组数据无解.
还有一个问题:输入的数最多能达到1000位,输出最多能达到3000位. 所以我们需要使用高精度算法.
以下是高精除以低精的模板.
#include<bits/stdc++.h>
using namespace std;
int b,a[100],c[100],x;
string ch;
int main(){
cin>>ch;
cin>>b;
int lena=ch.length();
for(int i=0;i<lena;i++){
if(isdigit(ch[i]))a[i+1]=ch[i]-'0';
}
for(int i=1;i<=lena;i++){
c[i]=(x*10+a[i])/b;
x=(x*10+a[i])%b;//按位相除
}
int lenc=1;
while(c[lenc]==0&&lenc<lena)lenc++;//删除前导零
for(int i=lenc;i<=lena;i++)cout<<c[i];
cout<<endl;
return 0;
}
而高精除以高精是用减法模拟除法,对被除数的每一位(这里的“一位”包含前面的余数,下同)都减去除数,一直减到这一位小于除数为止,实现会另讲.
程序实现
#include<bits/stdc++.h>
#define maxn 1010
using namespace std;
char str[maxn],ans[maxn];
int num[3*maxn];
bool count(int i){
int mod=0,k=0;
char *q;
for(int j=0;isdigit(str[j]);j++){
mod=mod*10+str[j]-'0';
ans[k++]=mod/i+'0';
mod%=i;
}
ans[k]='\0';
q=ans;
while(*q=='0')q++;
if(mod!=0)return false;
int h=0;
for(h=0;isdigit(*q);h++,q++){
str[h]=*q;
}
str[h]='\0';
return true;
}
int main(){
while(scanf("%s",str),str[0]!='-'){
int k=0;
if(!isdigit(str[1])){
cout<<"1"<<str<<endl;
continue;
}
for(int i=9;i>1;i--){
while(count(i)){
num[k++]=i;
}
}
if(strlen(str)>1){
printf("There is no such number.\n");
continue;
}
while(k>0)printf("%d",num[--k]);
printf("\n");
}
return 0;
}
本题总结
1. 1. 1.对于贪心,想的不多,思考方向不正确,应该从结论入手,考虑什么时候最小.
2. 2. 2.高精度不会写,导致很多题就算会了也拿不到分,令人遗憾.