最小回数を求めるには BFS!!(素振り)
問題概要
黒板に整数値 が書かれています。次のいずれかの操作を最小回数繰り返すことによって、整数値 の値を にしたいとします。
- を 倍して にする
- を十進法表記したときに、末尾の値を先頭に持ってくる
最小回数を求めてください。不可能である場合は -1 を出力してください。
制約
解法
この手の「最小回数」を求める問題は、原理的には BFS で解けます!
ただし、探索領域があまりにも広大であると、TLE となってしまいます。
今回の問題では、 なので、整数値 が 未満である場合のみ考えればよいです。なぜなら、今回の操作によって、整数値の桁数が減少することはないからです (値が減少すること自体はありえます)。
一般には、 未満の整数値のみ考えれば良いと言えるでしょう。
よって、 以上 未満の整数値に対応する頂点を用意して、操作によって変化する 2 値間に辺を張ったグラフを考えて、 から までの最短路を求めます。
シフト演算には の計算量を要することから、全体の計算量は と評価できます。
コード
#include <bits/stdc++.h> using namespace std; int main() { long long a, N; cin >> a >> N; queue<long long> que; vector<long long> dp(N * 10, -1); auto push = [&](long long v, long long p) -> void { if (v >= N * 10) return; if (dp[v] == -1) { que.push(v); dp[v] = dp[p] + 1; } }; que.push(1); dp[1] = 0; while (!que.empty()) { long long x = que.front(); que.pop(); // a 倍する push(x * a, x); // シフト操作する if (x % 10 != 0) { string sx = to_string(x); sx = sx.back() + sx.substr(0, sx.size()-1); istringstream si(sx); long long x2; si >> x2; push(x2, x); } } cout << dp[N] << endl; }