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的相同元素集合,不同的排列组合的一个集合

每个n元的置换都可以表示成若干个互不相交的循环置换的乘积,

设每个子循环置换的循环节为ci,则总的置换的循环节显然为lcm(c1,c2..cn)

#include<stdio.h>
#include<string.h>
struct stu{
    int num,period;
}a[205];
int n;
bool visit[205];
void cal_per()        //求每个元素的周期
{
    int t,i;
    memset(visit,false,sizeof(visit));
    for(i=1;i<=n;i++){
        if(!visit[i]){
            visit[i]=true;
            t=a[i].num;
            int cnt=1;
            while(t!=i){
                visit[t]=true;
                cnt++;
                t=a[t].num;
            }
            a[i].period=cnt;
            t=a[i].num;
            while(t!=i){
                a[t].period=cnt;
                t=a[t].num;
            }
        }
    }
}
int main()
{
    char s[205],c,temp;
    int i,j,k,next;
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        for(i=1;i<=n;i++)
            scanf("%d",&a[i].num);
        cal_per();
        while(scanf("%d",&k)&&k){
            gets(s);
            for(i=strlen(s);i<=n;i++)
                s[i]=' ';
            s[n+1]=0;
            memset(visit,0,sizeof(visit));
            for(i=1;i<=n;i++){
                if(!visit[i]){
                    for(j=1;j<=k%a[i].period;j++){
                        c=s[a[i].num];
                        s[a[i].num]=s[i];
                        visit[i]=true;
                        next=a[i].num;
                        while(next!=i){
                            visit[next]=true;
                            temp=s[a[next].num];
                            s[a[next].num]=c;
                            c=temp;
                            next=a[next].num;
                        }
                    }
                }
            }
            /*for(i=1;i<=n;i++)
                printf("%c",s[i]);
            printf("\n");*/
            puts(s+1);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-08-06 11:52:51

poj 1026 Cipher (置换群)的相关文章

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]

[ACM] POJ 1026 Cipher (组合数学,置换)

Cipher Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19228   Accepted: 5148 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 题解

看似简单的字符串处理,不过直接暴力法是会超时的. 故此需要优化,这里使用周期优化. 研究过数列序列的都知道,其实序列反复调用另外一个序列得到一个新的序列,都会出现周期的,问题是周期何时出现,如果利用这个周期. 这就需要分开每个数,使用一个新的数列记录每个数的周期,利用这个周期截去一大段数据,那么剩下的数据就很好处理了. 因为所有的周期数总和都不会超过n,数列的长度的,所以时间效率可以达到O(n),常数项为2. 其他难度,我觉得相对新手来说,就是执行的细节最困难了,比如下标的准确性,如何移动数据等

POJ 1026 Cipher(置换群)

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

POJ 1026 Cipher[置换]

Cipher 时限:1000MS 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 based on secret keys. They chose the secret key at their last meeting in Phila

POJ 1026 Cipher(置换)

                                                               Cipher Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19502   Accepted: 5239 Description Bob and Alice started to use a brand-new encoding scheme. Surprisingly it is not a P

POJ 1026 置换群的k次幂问题

题目大意: 给定了一组对应关系,经过k次幂后,得到新的对应关系b[i],然后将给定的字符串上的第i位字符放置到b[i]的位置上, 如果字符串长度不足n就用空格补足,这里的是空格,也就是str[i] = ' ',不是str[i]='\0' ,自己这里错了好几回就是找不到问题,看了别人代码才明白 置换群的k次幂问题不清楚,可以看看<<置换群快速幂运算+研究与探讨.pdf>> 这里初始给定的置换群要注意这个群不一定是一个循环集,我们要先统计出它的每一个循环集,然后每一个分别进行操作计算

【POJ】1026.Cipher

题解 置换群的快速幂,然而我姿势水平不高,样例过不去,然后才明白这个置换的意思是这个位置上的数代表要把原位置的某个数换过来 需要新开一个数组存结果 代码 #include <iostream> #include <cstdio> #include <vector> #include <set> #include <cstring> #include <ctime> #include <map> #include <a

POJ 3270-Cow Sorting(置换群)

题目地址:POJ 3270 题意:有n头牛,每头牛有一个独一无二的"愤怒值",要想把他们的愤怒值从小到大排序(交换任意两头牛位置所花费的时间为他们愤怒值的和),求最小的交换时间. 思路: 1.找出初始状态和结束状态(初始状态为题目所给,结束状态为从小到大排列) 2.画出置换群,在里面找循环.例如 初始状态:8 4 5 3 2 7 结束状态:2 3 4 5 7 8 从头开始找8->2->7->8,所以一个置换群是(8,2,7),然后在两个状态中去掉这三个点,从头开始找4