第二回 アルゴリズム実技検定 E – 順列 解説

問題

問題文は本家サイトにあります:第二回 アルゴリズム実技検定 E – 順列

問題概要

$1,2,\cdots,N$ の順列 $A_1,A_2,\cdots,A_N$ が与えられるので、各整数 $i\ (1\leqq i \leqq N)$ に対して次の条件を満たす最小の正整数 $j$ を答えなさい。

 条件: $x=i$ とする。 $x$ を $A_x$ で置き換えるという操作を $j$ 回行った後、 $x=i$ となる。

制約

$1\leqq N \leqq 100$

解説

リンク先の入力例にもありますが、1 3 2 5 6 4 の例を考えてみます。

$i=1$ の場合は次のようになります。まず、 $x=1$ です。 $x$ を $A_x$ で置き換えるのですが、これは $x$ を $A_1$ で置き換える、つまり、 $1$ に置き換えるということなので、置き換えた後は $x=1$ のままです。 $x=i$ だから、このときの $j$ は $1$ です。

$i=3$ の場合は次のようになります。まず、 $x=3$ です。 $x$ を $A_x$ で置き換えるのですが、これは $x$ を $A_3$ で置き換える、つまり、 $2$ に置き換えるということなので、置き換えた後は $x=2$ です。次に、 $x$ を $A_2$ で置き換える、つまり、 $3$ に置き換えるということなので、置き換えた後は $x=3$ となります。2回目で $x=i$ となるので、このときの $j$ は $2$ です。

【広告】

$i=5$ の場合は次のようになります。まず、 $x=5$ です。 $x$ を $A_x$ で置き換えるのですが、これは $x$ を $A_5$ で置き換える、つまり、 $6$ に置き換えるということなので、置き換えた後は $x=6$ です。次に、 $x$ を $A_6$ で置き換える、つまり、 $4$ に置き換えるということなので、置き換えた後は $x=4$ となります。 $A_4=5$ なので、もう一度置き換えると $x=5$ となります。3回目で $x=i$ となるので、このときの $j$ は $3$ です。

これは、最悪でも100回繰り返せば元に戻ってくるはずなので、それぞれの $i$ に対して実際に試してみると答えが得られます。C++で書けば、次のようになります。(下のコードでは、 $0$ から $N-1$ までの順列に置き換えて考えています)

#include <iostream>
#include <vector>
using namespace std;

int main() {

  int N; cin >> N;
  vector<int> A(N);
  for (int i = 0; i < N; i++) {
    cin >> A[i]; A[i]--;
  }

  for (int i = 0; i < N; i++) {
    int x = i, ans = 0;
    while (true) {
      ans++;
      x = A[x];
      if (x == i) {
        cout << ans << ' ';
        break;
      }
    }
  }
  return 0;
}