poj1026--Cipher(置换群)

题目链接:点击打开链接

题目大意:给出一个编码的顺序,每经过一次编码第i位上的字符回到第a[i]位上。然后给出一个k,和初始的串,问编码k次后的串是什么。

k可能会很大,不能暴力,所以要用置换群,找出轮换的环,假设环中有m个数,那么每编码m次,就代表这又回到了初始状态,可以用k%m,这样减少编码的次数。如果在记录轮换的位置,那么对于轮换中的第i个字符编码k次,就变成了轮换中的第(i+k)%m个字符。这样直接可以计算出最终的结果。

注意,题目不难,但是输入让人头疼,,,,经过多次wa,测试出只有(getline除外):

gets(str) ;

int len = strlen(str) ;

for(i = len ; i <= n ; i++)

str[i] = ‘ ‘ ;

而且一定要有后面的for,不然就错误,,,,,

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std ;
char str[210] , s[210] , ch ;
int cnt ;
int a[210] , vis[210] ;
vector <int> vec[210] ;
int vec_num ;
void grop(int n) {
    int i , j ;
    vec_num = 0 ;
    memset(vis,0,sizeof(vis)) ;
    for(i = 1 ; i <= n ; i++) {
        if( vis[ a[i] ] ) continue ;
        j = i ;
        while( !vis[ a[j] ] ) {
            vis[ a[j] ] = 1 ;
            vec[ vec_num ].push_back( j ) ;
            j = a[j] ;
        }
        vec_num++ ;
    }
}
int main() {
    int n , m , k , i , j , l , num , mod , temp ;
    while( scanf("%d", &n) && n ) {
        for(i = 1 ; i <= n ; i++) {
            scanf("%d", &a[i]) ;
        }
        for(i = 0 ; i < n ; i++) vec[i].clear() ;
        grop(n) ;
        while( scanf("%d", &k) && k ) {
            cnt = 0 ;
            memset(s,0,sizeof(s)) ;
            memset(str,0,sizeof(str)) ;
            /*getchar() ;
            while( ch = getchar() ) {
                if( ch == '\n' ) break ;
                str[++cnt] = ch ;
            }*/
            gets(str) ;
            int len = strlen(str) ;
            for(i = len ; i <= n ; i++)
                str[i] = ' ' ;
            for(i = 0 ; i < vec_num ; i++) {
                num = vec[i].size() ;
                for(j = 0 ; j < num ; j++) {
                    l = (j+k)%num ;
                    s[ vec[i][l] ] = str[ vec[i][j] ] ;
                }
            }
            for(i = 1 ; i <= n ; i++) {
                printf("%c", s[i]) ;
            }
            printf("\n") ;
        }
        printf("\n") ;
    }
    return 0 ;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-01 23:59:45

poj1026--Cipher(置换群)的相关文章

POJ1026 Cipher 【polya】

This question is not so difficult. First,my thoughts were we should use a lot of code to find out the loop block,but there is no need to do that . you just need to get every new position of char in the string. Algorithm is also easy , just like how d

Cipher(置换群)

Cipher Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20821   Accepted: 5708 Description Bob and Alice started to use a brand-new encoding scheme. Surprisingly it is not a Public Key Cryptosystem, but their encoding and decoding is base

poj 1026 Cipher (置换群)

链接:poj 1026 题意:给定n个大小1-n的不同的整数作为密钥,给定一个字符串, 求将该字符串经过k次编码后的字符串 分析:暴力求解会超时,可以利用置换群的知识解题 置换群:一个有限集合的一一变换叫做置换,一对对置换组成了置换群. 对于一个集合a(a[1],a[2],a[3]...a[n]) 通过置换可以变成 (b[a[1]],b[a[2]],b[a[3]]...b[a[n]]) b的作用就是置换(可以理解为某种函数的作用),将原来的集合映射成具有 相应次序的集合a',a'可以看做是a的相

hdu 1439 Cipher(置换群)

题目链接:hdu 1439 Cipher 题意: 给你一个n元的key,让你将一个字符串置换k次. 题解: 暴力将每个数的循环数找到,然后k%后对应填字符就行了. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=300; 6 char s[N],ans[N]; 7 int a[N],rep[N],n,k; 8 9 int ma

poj1026 Cipher

题目意思可概括为给定集合S = {1,..,n}的一个双射关系f, 求经过k次复合之后元素i对应的元素fk(i) (i∈S). 由于函数是双射,一个原像对应唯一一个像,同样一个像有唯一一个原像,考虑整个映射关系,存在整数m∈ Z,使得fm=f0=I. 即具有周期性. 每个元素映射回它自己有独立的周期T(i),整个映射的周期T=lcm(T(i)), i ∈ S. 独立处理更快,但对于本题也是刚刚卡过. 当然如果事先把所有询问读入加以预处理或者直接全部预处理会更快. 样例代码860ms卡过. htt

Bailian2818 密码【密码+置换】

2818:密码 总时间限制: 1000ms 内存限制: 65536kB 描述 Bob 和 Alice 开始使用一种全新的编码系统.它是一种基于一组私有钥匙的.他们选择了n个不同的数a1 , . . .,an, 它们都大于0小于等于n. 机密过程如下:待加密的信息放置在这组加密钥匙下,信息中的字符和密钥中的数字一一对应起来.信息中位于i位置的字母将被写到加密信息的第ai个位置, ai 是位于i位置的密钥.加密信息如此反复加密,一共加密 k 次. 信息长度小于等于n.如果信息比 n 短, 后面的位置

POJ 1026 Cipher(置换群)

题目链接 题意 :由n个数字组成的密钥,每个数字都不相同,都在1-n之间,有一份长度小于等于n的信息,要求将信息放到密钥下边,一一对应,信息不足n的时候补空格,然后将位置重新排列,将此过程重复k次,求最后的字符串序列,最后的空格不用输出. 思路 :如果按照最原始的求循环结的话会超时,因为k值范围很大.所以要用置换群,把每个的元素的循环求出来,直接对其取余即可.会3270的话,这个题理解起来挺容易的. 1 //1126 2 #include <stdio.h> 3 #include <st

poj 1026 Cipher

http://poj.org/problem?id=1026 这道题题意是给你一个置换群,再给你一个字符串,输出经过k次置换的字符串. 就是找循环节. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 3000 5 using namespace std; 6 7 int a[maxn],key[maxn]; 8 int n,k; 9 char str[maxn]

poj 3128 关于置换群的规律

Leonardo's Notebook Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2433   Accepted: 1037 Description - I just bought Leonardo's secret notebook! Rare object collector Stan Ucker was really agitated but his friend, special investigator S

Cracking The Vigenere Cipher

In order to crack "Vigenere Cipher" under the circumstance that the key length can be only 3, 4 or 5, I used frequency analysis to find possible keys and compared the Euclidean distance of all candidate keys calculated with "Relative freque