題意:給你n個數字,然後給你一個字符串,按照n個數字的指示,將字符串的字母重新排序
10(10個數字)
4 5 3 7 2 8 1 6 10 9
1 Hello Bob (1表示重排一次,空格後面就是要排的字符串)
1995 CERC (1995表示重排1995次)
BolHeol b
C RCE
例如: 4 5 3 7 2 8 1 6 10 9
H e l l o B o b (不夠的補空格)
得到: B o l H e o l b
分析:
key:
4 5 3 7 2 8 1 6 10 9(轉換為數組的下標為:3 5 2 6 1 7 0 6 9 8)
消息長度也為10,下標為0 1 2 3 4 5 6 7 8 9其實就是消息的下標按照key來置換,當經過若干次交換之後又會回到原來的位置,姑且稱這個交換的次數為循環長度loopLen例如:0->3->6->0,那麼0號位置的消息字符的循環長度loopLen[0] = 3 1->4->1,那麼1號位置的消息字符的循環長度loopLen[1] = 2這樣,我們算出每個位置的循環長度,在需要進行k次加密的時候,只需要交換該位置i上的字符k%loopLen[i]次就可以得到最終該位置上應該有的字符。
#include<iostream> #include<cstdio> using namespace std; int main() { int path[200][200]; //保存路徑 int keyarr[200]; //加密數字 int period[200]; //保存周期 int N; //加密包含多少個秘鑰 int k; //加密多少次 char src[500] ,ans[500];//需要加密的源字符串 for (scanf("%d",&N); N;scanf("%d",&N)){ int key; int i,j; memset(period,0,sizeof(int)*200); for(i=0;i<N;i++){ scanf("%d",&key); keyarr[i] = key -1;//因為索引是從0開始的 } for (i=0;i<N;i++){ j=i;//搜索第i個元素的周期 path[i][0]=j; period[i]=1; for (j=keyarr[j];j!=i;j=keyarr[j]){ path[i][period[i]++]=j; } } for (scanf("%d",&k);k;scanf("%d",&k)){ getchar();//讀空緩沖區裡面的內容 gets(src); for (i=0;src[i];i++); for (;i<N;i++)src[i]=' ';//不夠的補上空格 for (i=0;i<N;i++)ans[path[i][k%period[i]]]=src[i]; ans[N]=0; puts(ans); } printf("\n"); } return 0; } <SPAN style="FONT-SIZE: 24px"><STRONG><SPAN style="LINE-HEIGHT: 26px; WHITE-SPACE: pre-wrap"> </SPAN></STRONG></SPAN>