pku 1026 Cipher 置换群
http://poj.org/problem?id=1026
题意:
给定长度为n的序列key[],key[i](表示第i个字符置换一次后跑到key[i]的位置)然后给出数字k以及字符串seq[],输出经过k次加密后的字符串,字符串的长度总是满足长度为n如果后边无字符用空格代替。
每一次的加密过程为:
例如 4 5 3 7 2 8 1 6 10 9, Hello Bob, 然后从左到右让字符串的每一个字符与一个数字对应:
4 5 3 7 2 8 1 6 10 9
H e l l o B o b ‘ ’ ‘ ‘
假如加密后的到的新字符串用res[]表示,那么加密过程就是res[4] = H, res[5] = e, res[3] = l····。
连续加密K次,每一次在前一次得到的信息之上再加密。
这里模拟会超时,我们求出每个字符串的置换周期t[i],属于同一轮换的置换周期一样,然后用k%t[i],就可得到最后该位置经过k次加密后值了。。
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 100000007 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 100007 #define N 207 using namespace std; //freopen("din.txt","r",stdin); int key[N],t[N],s[N]; char seq[N],res[N]; int n; void get_T(){ int i,j; CL(t,0); for (i = 1; i <= n; ++i){ if (t[i] == 0){ int top = 0; int pos = key[i]; int ct = 1; s[0] = i; while (pos != i){ ct++; s[++top] = pos;//记录属于同一轮换的点 pos = key[pos]; } for (j = 0; j <= top; ++j) t[s[j]] = ct;//记录周期 } } } int main(){ // freopen("din.txt","r",stdin); int i,j,T; while (~scanf("%d",&n)){ if (!n) break; for (i = 1; i <= n; ++i) scanf("%d",&key[i]); get_T();//得到每个字符的置换周期 while (scanf("%d",&T) && T){ getchar(); gets(seq + 1); for (i = strlen(seq + 1) + 1; i <= n; ++i) seq[i] = ' '; seq[n + 1] = '\0'; for (i = 1; i <= n; ++i){ int pos = i; for (j = 0; j < T%t[i]; ++j) pos = key[pos];//得到该位置经过K次加密后的位置 res[pos] = seq[i]; } res[n + 1] = '\0'; printf("%s\n",res + 1); } printf("\n"); } return 0; }