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 Sarah Kepticwas unimpressed. 
— How do you know it is genuine? 
— Oh, it must be, at that price. And it is written in the da Vinci code. Sarah browsed a few of the pages. It was obvious to her that the code was a substitution cipher, where each letter of the alphabet had been substituted by another letter. 
— Leonardo would have written the plain-text and left it to his assistant to encrypt, she said. And he must have supplied the substitution alphabet to be used. If we are lucky, we can find it on the back cover! She turned up the last page and, lo and behold, there was a single line of all 26 letters of the alphabet: 
QWERTYUIOPASDFGHJKLZXCVBNM 
— This may be Leonardo‘s instructions meaning that each A in the plain-text was to be replaced by Q, each B withW, etcetera. Let us see... To their disappointment, they soon saw that this could not be the substitution that was used in the book. Suddenly, Stan brightened. 
— Maybe Leonardo really wrote the substitution alphabet on the last page, and by mistake his assistant coded that line as he had coded the rest of the book. So the line we have here is the result of applying some permutation TWICE to the ordinary alphabet! Sarah took out her laptop computer and coded fiercely for a few minutes. Then she turned to Stan with a sympathetic expression. 
— No, that couldn‘t be it. I am afraid that you have been duped again, my friend. In all probability, the book is a fake.

Write a program that takes a permutation of the English alphabet as input and decides if it may be the result of performing some permutation twice.

Input

The input begins with a positive number on a line of its own telling the number of test cases (at most 500). Then for each test case there is one line containing a permutation of the 26 capital letters of the English alphabet.

Output

For each test case, output one line containing Yes if the given permutation can result from applying some permutation twice on the original alphabet string ABC...XYZ, otherwise output No.

Sample Input

2
QWERTYUIOPASDFGHJKLZXCVBNM
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Sample Output

No
Yes

初看这道题真的一脸懵,就去搜。原来有规律qwq。代码的实现很简单,关键是涉及这方面的知识。

摘自:https://blog.csdn.net/lianai911/article/details/49474067

题目大意:

给你一行共 26 个字母,代表一个置换。问:这个置换能否为某个置换平方的结果。

解题思路:

这道题可参考《置换群快速幂运算研究与探讨》,里边有详解。这里放上结论。

结论一: 一个长度为 l 的循环 T,l 是 k 的倍数,则 T^k 是 k 个循环的乘积,每个

循环分别是循环 T 中下标 i mod k=0,1,2… 的元素按顺序的连接。 
结论二:一个长度为 l 的循环 T,gcd(l,k)=1,则 T^k 是一个循环,与循环 T 不一

定相同。

结论三:一个长度为 l 的循环 T,T^k 是 gcd(l,k)个循环的乘积,每个循环分别是循

环 T 中下标 i mod gcd(l,k)=0,1,2… 的元素的连接。

这倒题中,应用上边的结论来判断这个置换是否为某个置换平方的结果。

一个置换平方可得到:循环节为奇数的置换的平方仍为奇数项的置换,循环节为偶数

的置换的平方分裂成了两个循环节相同的置换。

那么当前置换是由什么置换而来的:

对于奇数项的置换,有可能是由奇数项的置换平方得到的,也有可能是有偶数项的置

换平方得到的。对于偶数项的置换,它一定是原始置换为偶数项的置换分裂得到的。

而且当前置换中偶数项的置换一定成对出现。

那么问题就变为了:对于偶数项的置换,是否成对出现。

那么,我们现在查找 26 个字母的所有置换,计算出每个置换的循环节长度。统计循

环节长度的个数。遍历查找偶数项的置换数目,如果出现奇数,则输出"No",否则

输出"Yes"。



 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=30;
 6 char a[maxn];
 7 int b[maxn];
 8 int c[maxn];
 9 bool flag[maxn];
10
11 bool solve()
12 {
13     memset( flag, 0, sizeof flag);
14     memset( c, 0, sizeof c);
15     bool cheek=true;
16     for(int i=0;i<26;i++){
17         if(!flag[i]){
18             flag[i]=1;
19             int num=1,next;
20             next=b[i];
21             while( !flag[next]){
22                 flag[next]=1;
23                 num++;
24                 next=b[next];
25             }
26             c[num]++;
27         }
28     }
29     for(int i=2;i<=26;i+=2){
30         if(c[i]&1){
31             cheek=false;
32             break;
33         }
34     }
35     return cheek;
36 }
37
38 int main()
39 {
40     int n;
41     while( ~scanf("%d",&n)){
42         getchar();
43         while(n--){
44             scanf("%s",a);
45             for(int i=0;i<26;i++)
46                 b[i]=a[i]-‘A‘;
47             bool cheek=solve();
48             if(cheek) printf("Yes\n");
49             else printf("No\n");
50         }
51
52     }
53
54     return 0;
55 }

原文地址:https://www.cnblogs.com/ZQUACM-875180305/p/9054041.html

时间: 2024-10-10 14:06:44

poj 3128 关于置换群的规律的相关文章

POJ 3128 Leonardo&#39;s Notebook [置换群]

传送门 题意:26个大写字母的置换$B$,是否存在置换$A$满足$A^2=B$ $A^2$,就是在循环中一下子走两步 容易发现,长度$n$为奇数的循环走两步还是$n$次回到原点 $n$为偶数的话是$\frac{n}{2}$次,也就是说分裂成了两个循环 综上$B$中长度为偶数的循环有奇数个就是不存在啦 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #inclu

poj 3128 Leonardo&#39;s Notebook (置换群的整幂运算)

题意:给你一个置换P,问是否存在一个置换M,使M^2=P 思路:资料参考 <置换群快速幂运算研究与探讨> https://wenku.baidu.com/view/0bff6b1c6bd97f192279e9fb.html 结论一: 一个长度为 l 的循环 T,l 是 k 的倍数,则 T^k 是 k 个循环的乘积,每个循环分别是循环 T 中下标 i mod k=0,1,2- 的元素按顺序的连接. 结论二:一个长度为 l 的循环 T,gcd(l,k)=1,则 T^k 是一个循环,与循环 T 不一

【POJ 3128】Leonardo&#39;s Notebook

这道题的问题就是说能否对一个给定的置换进行开方运算 关于这个问题讲的最为详细的是05年集训队论文 潘震皓:<置换群快速幂运算研究与探讨> 对于一个长度为l的轮换,若gcd(l,k)==1,则可以开k方 若gcd(l,k)!=1则对于单个循环是不能开k方的 而若有m个长度为l的轮换,只需要保证gcd(m*l,k)==m就可以 因为开k方是k次方的逆运算,只要保证目标轮换的k次方会分裂成m个数就好了 而若能保证gcd(m*l,k)==m,则m|k,且gcd(l,k/m)==1,即m为k的因子 则最

poj 3128 Leonardo&#39;s Notebook(置换的幂)

http://poj.org/problem?id=3128 大致题意:输入一串含26个大写字母的字符串,可以把它看做一个置换,判断这个置换是否是某个置换的平方. 思路:详解可参考置换群快速幂运算 研究与探讨. 可以先正着考虑一个置换的平方出现什么情况.对于置换中的循环,若其长度为偶数,平方以后一定分成了两个长度相等的循环,若长度是奇数,平方以后仍是一个循环,长度不变.因此,考虑当前置换,若某个循环的长度为偶数,那么它一定是原始置换平方得来的,而且等长度的循环一定有偶数个.对于长度为奇数的循环,

POJ 3128 Leonardo&#39;s Notebook (置换)

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

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的相

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

POJ 2229 Sumsets(找规律,预处理)

题目 参考了别人找的规律再理解 /* 8=1+1+1+1+1+1+1+1+1 1 8=1+1+1+1+1+1+1+2 2 3 8=1+1+1+1+2+2 8=1+1+1+1+4 4 5 8=1+1+2+2+2 8=1+1+2+4 6 7 8=2+2+2+2 8=2+2+4 8=4+4 8=8 8~9 */ /* 以下引用自博客:http://blog.csdn.net/scorpiocj/article/details/5940456 如果i为奇数,肯定有一个1,把f[i-1]的每一种情况加一个

poj 1721 CARDS(置换群)

题目链接:poj 1721 CARDS 题意: 看了半天才看懂,就是一次置换为b[i]=a[a[i]],a[i]=b[i]. 现在已经知道了置换了多少次和当前的序列,问你最原来的序列为 题解: 将这个置换的循环次数ans找出来,再做ans-s次就行了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define F(i,a,b) for(int i=a;i<=b;++i) 5 usi