Bod 和 Alice 计划使用一种全新的编码方案,令人惊讶的是这不是一个公开的公匙密码,但是他们的编码基于密匙,在
Philadelphia on February 16th他们的会议中选择了密匙,他们选择的密匙是一个两两不等的整数序列,a1.....an,大于0并且小于等于n,编码基于一下原则。
下面的信息是关键,这样关键的人物信息和数字相对齐,一个字符在i位置,编码的时候把他放在ai,ai就是相应数字位置的关键,并且他们以同样的编码信息进行编码,这个过程重复k次,在k次以后他们交换彼此的编码。
这段信息的长度小于或者等于n,如果小于n,那么就在信息的后面能添加空格使它等于n,
写一个程序完成这个编码
本题先开始给了n个数,代表编码的方案,例如
Sample Input
10 4 5 3 7 2 8 1 6 10 9 1 Hello Bob 1995 CERC 0 0
Sample Output
BolHeol b C RCE
给出的4 5 3 7 2 8 1 6 10 9表示:第一个位置的字符经过一次置换后会出现在第4位置, 第二位置的编号会到第五位置.....所以可以得到所有的置换群为(1,4,7)(2,5)(3)(6,8)(9,10) 这是经过0次变换的结果。经过k次变换只需要单独的在每个群里进行移动就行了,所以,求出置换群后进行下标取模就行了。#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define LL long long #define INF 0x3f3f3f3f #define bug puts("************") using namespace std; const int N=300; int index[N]; int vis[N]; int num[N]; ///置换群的大小 int arr[N][N]; ///记录每个置换群的内容 char s[N]; char str[N]; int main(){ int n; while(~scanf("%d",&n),n){ memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); for(int i=1;i<=n;i++){ scanf("%d",&index[i]); } int cnt=0; ///置换群的总个数 for(int i=1;i<=n;i++){ if(!vis[i]){ vis[i]=1; arr[cnt][num[cnt]++]=i; int tmp=index[i]; while(!vis[tmp]){ vis[tmp]=1; arr[cnt][num[cnt]++]=tmp; tmp=index[tmp]; } cnt++; } } // for(int i=0;i<cnt;i++){ // for(int j=0;j<num[i];j++){ // printf("%d ",arr[i][j]); // } // cout<<endl; // } int m; while(~scanf("%d",&m),m){ gets(s); int len=strlen(s); ///下标0处多读了一个空格。字符串下标从1开始 for(int i=len;i<=n;i++) s[i]=' '; for(int i=0;i<cnt;i++){ for(int j=0;j<num[i];j++){ str[arr[i][(j+m)%num[i]]-1]=s[arr[i][j]]; } } str[n]='\0'; printf("%s\n",str); } puts(""); } return 0; }