abc235_d Multiply and Rotate 题解

Multiply and Rotate

题意

给定两个整数 \(a\)\(n\),有一个整数 \(x\),初始值为 \(1\),有两种操作:

  1. \(x\) 变成 \(x \times a\)
  2. \(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;
}
posted @ 2023-05-17 21:00  wnsyou  阅读(24)  评论(0编辑  收藏  举报