切換
舊版
前往
大廳
主題

ZeroJudge - c109: 00306 - Cipher 解題心得

Not In My Back Yard | 2020-08-07 00:00:18 | 巴幣 0 | 人氣 196

題目連結:


題目大意:
輸入有多筆測試資料。每筆第一列給定一正整數 n (0 < n ≦ 200, n = 0 時代表輸入結束),接著的一列輸入有 n 個正整數,為 1 ~ n 的一種排列,代表加密的密鑰。

接著有若干列,每列先給定一正整數 k(k 可能很大,但是必定可以被 C 語言的 int 儲存。當 k = 0 時,代表這組測試資料的結尾),代表要將明文重複加密 k 次。緊接著同一列給定一字串(與前面的 k 以一個空白字元分隔,且字串長度保證 ≦ n),代表明文的內容。

加密的方式為:
將字串的每個字元依序與密鑰中的每一個數字對齊(如果字串長度不足 n ,則在後面補上空白字元)。如
明文: a b c d
密鑰: 4 1 2 3
而加密的方法即是將字元放到現在對應到的密鑰之值的位置。如上例加密一次後會變為
密文: b c d a
密鑰: 4 1 2 3
而上述的過程可以一直重複。

對於每個 k 值,輸出加密 k 次後的字串。每組測資後請輸出一空白列,參見範例輸出。



範例輸入:
10
4 5 3 7 2 8 1 6 10 9
1 Hello Bob
2 Hello Bob
1995 CERC
0
5
1 2 3 5 4
1 Hello
0
0


範例輸出:
BolHeol  b
lelBo Hob
C RCE     

Helol


解題思維:
因為 k ,也就是需要的加密次數,可能很大。因此,我們需要預先計算每個位置的字元(第 1 個字元 ~ 第 n 個字元)在一次加密、二次加密、……、之後的位置。因為 n 是有限的,因此這個對於單一位置的字元的加密,其必定會循環且週期不超過 n 。

所以,我們預先算每個字元的循環以及週期之後,遇到每個 k 值以及明文時,先掃過一次明文。對於每個字元,將 k 取除以該位置的週期之餘數,然後將餘數對應到循環裡應該要去的位置(即第「餘數之值」個),然後將該字元移到該位置(可以用另一個字串或是字元陣列當作暫存)。

跑完上述之後輸出該加密後字串即是所求。




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作