Poj1026 Cipher(置换群幂运算)

题意:

给定一个排列置换,若干次询问
每次询问给定一个整数k和一个字符串
输出字符串进行k次置换得到的新串

数据范围:n<=200

解法:

置换是排列,可以抽象为若干有向环,我们要做的就是将每个点在环上走k步。

预处理出置换中的所有环,然后每个环中的元素单独处理,步数k对环的大小取模,可以O(1)计算出终点。

code:

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int maxm=205;
int mark[maxm];
char s[maxm];
char ans[maxm];
int a[maxm];
int n,k;
signed main(){
    while(cin>>n&&n){
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)mark[i]=0;
        vector<int>cir[maxm];
        int cnt=0;
        for(int i=1;i<=n;i++){//找环
            if(!mark[i]){
                cnt++;
                int x=i;
                while(!mark[x]){
                    mark[x]=1;
                    cir[cnt].push_back(x);
                    x=a[x];
                }
            }
        }
        while(cin>>k&&k){
            getchar();
            gets(s+1);
            int len=strlen(s+1);
            while(len<n){
                s[++len]=' ';
            }
            for(int i=1;i<=cnt;i++){
                int cc=cir[i].size();
                for(int j=0;j<cc;j++){
                    int pos=(j+k)%cc;//计算j走k步到达的位置
                    ans[cir[i][pos]]=s[cir[i][j]];
                }
            }
            for(int i=1;i<=n;i++){
                cout<<ans[i];
            }
            cout<<endl;
        }
        puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107348369
今日推荐