abc235_d Multiply and Rotate 题解
Multiply and Rotate
题意
给定两个整数 \(a\) 和 \(n\),有一个整数 \(x\),初始值为 \(1\),有两种操作:
- 将 \(x\) 变成 \(x \times a\)。
- 在 \(x > 10\) 且 \(x\) 不是十的倍数的情况下可以执行此操作: 将 \(x\) 当成一个字符串,将其循环右移一次。
求最少执行多少次操作能把 \(x\) 变成 \(n\),若无法将其变为 \(n\),输出 -1
。
思路
简单的广搜题。
首先,我们可以发现,操作 \(1\) 只能把 \(x\) 变大,操作 \(2\) 既可以变小也可以变大,但并不能把 \(x\) 的位数缩小,所以就可以推出来:当 \(x\) 的位数比 \(n\) 多时,是不可能再经过若干次操作变成 \(n\) 的,也就自然不用往下进行了。
有了这个剪枝,这题也就可以轻松地过掉了。
详见代码。
Code
点击查看代码
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 1e6 + 10, INF = 1e6;
int a, n, f[MAXN];
queue<long long> q;
void Record (long long x, int lv) {
if (x >= INF || f[x] != -1) { // 这种情况不合法或者有更优的操作次数
return ; // 筛掉
}
f[x] = lv; // 记录
q.push(x);
}
// 操作 2 会将最低位移到第高位,这里就是在求需要乘几才能把它移到最高位
long long W (long long x) {
long long sum = 1;
while (x) {
x /= 10;
sum *= 10;
}
return sum / 10;
}
void bfs () {
Record(1, 0); // 初始状态
while (!q.empty()) {
long long t = q.front();
q.pop();
Record(t * a, f[t] + 1); // 操作 1
if (t > 10 && t % 10) { // 满足要求,可以执行操作 2
Record(t / 10 + (t % 10) * W(t), f[t] + 1); // 操作 2
}
}
}
int main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> a >> n;
for (int i = 1; i < INF; i++) { // 无脑初始化
f[i] = -1;
}
bfs();
cout << f[n]; // 输出答案
return 0;
}