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;
}

 

posted @ 2012-09-04 19:39  E_star  阅读(204)  评论(0编辑  收藏  举报