第一題 密文排列

       Alice 要傳送一份機密訊息 P 給 Bob,為了避免機密訊息曝光,
打算使用一種換位法來 保護此機密訊息。
換位法的程序是先輸入一個數字 K當作列數,並以機密訊息長
度當作行數,然後將機密訊息每個字母以鋸齒狀的方式進行排
列,排列完成後,從左至右、由上到下讀取, 形成密文 C。

舉例來說,若輸入 K=3,機密訊息 P="UNIVERSITY",則換位排列如下圖::
U       E       T  
  N   V   R   I   Y
    I       S      
則產生輸出的密文為 C="UETNVRIYIS"。

輸入說明
輸入 1個正整數 1<K≦10,再輸入原始機密訊息字串 P,兩輸入間以空格隔開。

輸出說明
輸出答案為密文字串 C。

範例

輸入 輸出
3 SAVEYOURSELF SYSAEOREFVUL
4 SOUTHERNTAIWAN SRAOENWNUHTITA

分析

本提乍看之下,好像要使用陣列放入字元,但其實不用,請細心觀察
取字的變化,下圖為 3 、4 及 5 列,以字的位置代替文字(0表示第 0 個字)

3 列
0       4       8      
  1   3   5   7   9   11
    2       6       10  
請注意右斜字元 0、1、2,4、5、6,8、9、10,第一排字 0、4、8,間隔為 4
第二排字 1、5、9,間隔亦為 4,第三排字 2、6、10,間隔還是 4,4 從何
而來? (3列-1) * 2,即為所求
另外,左斜字元 4、3,2,8、7、6,起點為間隔 -1。
除了前後排不需要以外,中排 3、7、11,間隔也是 4。

4 列
0           6           12  
  1       5   7       11   13
    2   4       8   10      
      3           9        

由上面推論可知間隔為 (4列-1) * 2 = 6,左斜起點為 5。

5 列
0               8              
  1           7   9           15
    2       6       10       14  
      3   5           11   13    
        4               12      
由上面推論可知間隔為 (5列-1) * 2 = 8,左斜起點為 7。



unsigned dis, i, j, k, t;
k = 5;
cin >> k >> s; //輸入 k 值與字串 s
k--; //列 -1
t = dis = k * 2; // (列 - 1)再*2 就是間距
for (i = 0;i <= k;i++) { //i 表示每一列(從 0 開始至 (列-1)
     for (j = i, t = dis - i;j < s.length();j += dis, t += dis) {
         cout << s.substr(j, 1); //輸出右斜字元
         if ((i != 0) && (i != k)) { //去掉首列與末列不輸出左斜字元
             if (t<s.length()) cout << s.substr(t, 1); //輸出左斜字元
         }
     }
}
cout << "\n";