简要题意:
一个数把各位数字乘起来得到另一个数。已知另一个数,求最小的“一个数”。
首先,你发现,假设答案为 m m m ,给定 n n n ,那么此时 m m m 的各位数字之积为 n n n.
既然已知 n n n,那么我们就应该分解 n n n.
比方说, 18 = 2 × 9 18 = 2 \times 9 18=2×9,那么答案就是 29 29 29.
再比方说, 250 = 2 × 5 3 250 = 2 \times 5^3 250=2×53,那么答案就是 2555 2555 2555.
那么,无解情况是什么?
比方说, 999 = 3 3 × 37 999 = 3^3 \times 37 999=33×37,此时需要有一个 37 37 37,但是 37 37 37 是两位数,所以不合法。
因此。 n n n 的质因子不能超过 9 9 9. 否则不合法。
知道这些之后,我们只要从 9 9 9 到 2 2 2 进行除法即可。(高精度除法其实挺简单的哦~)
那么你说了,怎么保证得到的答案一定比 n n n 大呢?
假设存在答案。那么 n n n 每分解一个 ≤ 9 \leq 9 ≤9 的数就会在原来的答案拼上一位,那么原来的答案至少也是 × 10 \times 10 ×10.
那么也就是说, n n n 每次会除掉 2 2 2 ~ 9 9 9,但答案会 × 10 \times 10 ×10. 所以答案肯定比 n n n 大。证毕。
时间复杂度: O ( size n ) O( \operatorname{size}_n ) O(sizen)
实际得分: 100 p t s 100pts 100pts.
这也叫蓝题???
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int main(){
string s; cin>>s;
vector<int>v; int l=0;
int x=9; while(x>=2) {
int sum=0;
for(int i=0;i<s.size();i++) sum=(sum*10+s[i]-'0')%x; //试除
if(!sum) { //能整除
v.push_back(x);
for(int i=0;i<s.size();i++) {
sum=sum*10+s[i]-'0';
s[i]=sum/x+'0'; sum%=x; //除掉
} l=(s[l]=='0')?(++l):l; //l 表示,除完一次之后被砍掉的位数
} else x--;
} if(l!=s.size()-1) puts("There is no such number!");
//如有解,那么 2~9 的质因子就应该把 n 变成 1,即全部砍掉。否则说明无解。
else {
reverse(v.begin(),v.end()); //我们是从大到小除的,翻转
for(int i=0;i<v.size();i++) printf("%d",v[i]);
putchar('\n');
}
return 0;
}