[POJ1062 Cipher]

[关键字]:数学 置换群

[题目大意]:给出一组置换,然后要求出把给出的文字按位置置换k此后的信息。

//==========================================================================================================================================

[分析]:首先求出这个置换的循环,并记录循环的长度环每个位置上的值。找到每个位置所属的循环然后它在循环中的位置加k再对循环长度取模就是它的最终位置。

[代码]:

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<algorithm>

using namespace std;



int n,m,len,sum,test;

int a[205],c[205][205],belong[205],d[205];

char s[205],s2[205],ch;

bool b[205];



void Solve()

{

    sum=0;

    memset(b,0,sizeof(b));

    memset(c,0,sizeof(c));

    memset(belong,0,sizeof(belong));

    memset(d,0,sizeof(d));

    for (int i=1;i<=n;++i)

        if (!b[i])

        {

            ++sum;

            int p=i;

            while (!b[p])

            {

                b[p]=1;

                belong[p]=sum;

                c[sum][++c[sum][0]]=p;

                d[p]=c[sum][0];

                p=a[p];

            }

        }

    /*for (int i=1;i<=sum;++i)

    {

        for (int j=0;j<=c[i][0];++j) printf("%d ",c[i][j]);

        printf("\n");

    }*/

    memset(s2,0,sizeof(s2));

    for (int i=1;i<=n;++i)

    {

        int pos=belong[i],size=c[pos][0];

        s2[c[pos][(d[i]+m-1)%size+1]]=s[i];

        //printf("%d %d\n",i,c[pos][(d[i]+m-1)%size+1]);

    }

    for (int i=n;i>=1;--i)

        if (s2[i]==' ') s2[i]='\0'; else break;

    printf("%s\n",s2+1);

}



int main()

{

    freopen("in","r",stdin);

    freopen("out","w",stdout);

    while (scanf("%d",&n),n)

    {

        if (++test!=1) printf("\n");

        for (int i=1;i<=n;++i) scanf("%d",&a[i]);

        while (scanf("%d",&m),m)

        {

            len=0;

            scanf("%c",&ch);

            while (scanf("%c",&ch),ch!='\n') s[++len]=ch;

            while (len<n) s[++len]=' ';

            s[n+1]='\0';

            Solve();

        }

    }

    return 0;

}

你可能感兴趣的:(poj)