Codeforces-1681D: Required Length
题目传送门:Codeforces-1681D
题目
题目截图
样例描述
题目大意
给定 n n n 和 x x x。每一次,可以从 x x x 的各位数中选择一位数 y y y 进行相乘得到 x = x ⋅ y x=x \sdot y x=x⋅y。问经过多少次操作后, x x x 可以达到长度 n n n。
题目解析
虽然
1
0
19
10^{19}
1019 看起来很大,但我们需要注意到,
x
x
x 每次乘的数均不会超过
10
10
10。也就是说,我们对
10
10
10 以内的数找质因数,有
2
,
3
,
5
,
7
2,3,5,7
2,3,5,7,最终得到的值会以
x
×
2
a
×
3
b
×
5
c
×
7
d
x \times 2^a \times 3^b \times 5^c \times 7^d
x×2a×3b×5c×7d 这样的形式呈现。由于最终的值不会超过
1
0
19
10^{19}
1019,因此,我们可以得出
a
≤
log
2
1
0
19
,
b
≤
log
3
1
0
19
,
c
≤
log
5
1
0
19
,
d
≤
log
7
1
0
19
a \le \log_2 10^{19}, b \le \log_3 10^{19}, c \le \log_5 10^{19}, d \le \log_7 10^{19}
a≤log21019,b≤log31019,c≤log51019,d≤log71019,它们的乘积在一个遍历可接受的范围内。因此我们可以直接搜索,用 BFS 的方式得到结果。
值得注意的是,每次乘最大的数字并不能保证最优解,只是局部最优,因为我们无法保证这次最优可以导致下一次也最优。比如官方题解给的样例:
5
,
403
5,403
5,403。我们先乘
4
4
4,结果为
1612
1612
1612,下一次乘
6
6
6 是达不到要求长度的。但若我们先乘
3
3
3,结果为
1209
1209
1209,我们再乘个
9
9
9 就可以达到要求长度了。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 4e6 + 7;
map<LL, int> d;
LL q[maxn];
LL len(LL x) {
LL c = 0;
while(x > 0) ++c, x/=10;
return c;
}
int main() {
LL n, x, l=0, r=0;
cin >> n >> x;
q[r++] = x, d[x] = 0;
while(l<r) {
LL x = q[l++];
if(len(x) >= n) continue;
while(x > 0) {
LL t = 1ll * q[l-1] * (x % 10);
x /= 10;
if(d.count(t)) continue;
d[t] = d[q[l-1]] + 1;
if(len(t) == n) {
cout << d[t] << endl;
return 0;
}
q[r++] = t;
}
}
cout << -1 << endl;
return 0;
}