POJ 1026 - Cipher
http://poj.org/problem?id=1026
概要
1 .. N の順列 a[1], ..., a[N] が与えられ,これを用いて文字列を暗号化する.
整数 k と長さが N 以下の文字列 s に対して,「s'[a[i]] <- s[i]」という処理を k 回繰り返すことで暗号化する. s の長さが N に満たないとき,s の末尾に長さが N になるまで空白を追加する.
暗号化された文字列を答える.
制約
- 0 < n <= 200
解法
k についての制約が無く,おそらく結構大きい値がくるので,本当に k 回繰り返すと TLE すると思われる.
i に対して何回置換 a を作用させると再び i になるか(= 周期)を予め計算しておき,周期で割った値の分だけ処理を行う. 周期は高々 N である.
poj/1026.cc1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 int main() 6 { 7 ios::sync_with_stdio(false); 8 int N; 9 while (cin >> N && N != 0) { 10 vector<int> a(N); 11 for (int i = 0; i < N; i++) { 12 cin >> a[i]; 13 --a[i]; 14 } 15 vector<int> periods(N, 1); 16 for (int i = 0; i < N; i++) { 17 for (int j = a[i]; j != i; j = a[j]) { 18 ++periods[i]; 19 } 20 } 21 22 int k; 23 while (cin >> k && k != 0) { 24 cin.ignore(); 25 string msg; 26 getline(cin, msg); 27 string buf(N, ' '), ans(N, ' '); 28 copy(msg.begin(), msg.end(), buf.begin()); 29 for (int i = 0; i < N; i++) { 30 const int M = k % periods[i]; 31 int j = i; 32 for (int c = 0; c < M; c++) { 33 j = a[j]; 34 } 35 ans[j] = buf[i]; 36 } 37 cout << ans << endl; 38 } 39 cout << endl; 40 } 41 return 0; 42 }