E - Permute K times 解説 by en_translator
This problem can be solved with a technique called doubling.
The following is references on doubling (in Japanese).
First, for \(k=0,1,\dots,59\), consider finding the following array \(P_k\):
- \(P_{k,i} :=\) (after \(2^k\) operations, the \(i\)-th element of the resulting sequence contains the \(P_{k,i}\)-th element of the sequence before the operations)
First, \(P_0 = X\).
Furthermore, one can obtain \(P_k\) from \(P_{k-1}\) as follows.
- \(P_{k,i} = P_{k-1}[P_{k-1,i}]\)
Intuitively, applying “\(2^{k-1}\) operations” twice mean applying “\(2^k\) operations.”
In general, for a sequence \(L\) corresponding to \(l\) operations and a sequence \(R\) corresponding to \(r\) operations, \(T_i=R[L_i]\) yields a sequence \(T\) corresponding to \(l+r\) operations. Let us call it “composition of operations.”
One can solve the original problem if we can obtain, based on these sequences \(P_i\), a sequence \(Q\) such that after \(K\) operations, the \(i\)-th element of the resulting sequence contains the \(Q_i\)-th element of the original sequence. How can we obtain it?
This can be done in the same manner as the fast exponentiation. Specifically, one can find it as follows.
- Let \(Q=(1,2,\dots,N)\) (corresponding to \(0\) operations).
- For \(i=0,1,\dots,59\), repeat the following.
- If the remainder when \(K\) is divided by \(2\) is \(1\), then compose \(Q\) and \(P_i\).
- Then, divide \(K\) by \(2\) (truncating the decimal part).
Sample code (C++):
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
long long k;
cin >> n >> k;
vector<vector<int>> p(60,vector<int>(n+1));
for(int i=1;i<=n;i++){
cin >> p[0][i];
}
vector<int> a(n+1);
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int lv=1;lv<60;lv++){
for(int i=1;i<=n;i++){
p[lv][i]=p[lv-1][p[lv-1][i]];
}
}
vector<int> q(n+1);
for(int i=1;i<=n;i++){q[i]=i;}
for(int lv=0;lv<60;lv++){
if(k%2){
for(int i=1;i<=n;i++){
q[i]=p[lv][q[i]];
}
}
k/=2;
}
for(int i=1;i<=n;i++){
if(i>=2){cout << " ";}
cout << a[q[i]];
}cout << "\n";
return 0;
}
投稿日時:
最終更新: