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;

}

 

你可能感兴趣的:(pku)