POJ1721_CARDS【置换群】

CARDS

Time Limit: 1000MS
Memory Limit: 10000K

Total Submissions: 1452
Accepted: 776

Description

Alice and Bob have a set of N cards labelled with numbers 1 ... N (so that no two cards have the same label) and a shuffle machine. We assume that N is an odd integer.

The shuffle machine accepts the set of cards arranged in an arbitrary order and performs the following operation of double shuffle : for all positions i, 1 <= i <= N, if the card at the position i is j and the card at the position j is k, then after the completion
of the operation of double shuffle, position i will hold the card k.

Alice and Bob play a game. Alice first writes down all the numbers from 1 to N in some random order: a1, a2, ..., aN. Then she arranges the cards so that the position ai holds the card numbered ai+1, for every 1 <= i <= N-1, while the position aN holds the
card numbered a1.

This way, cards are put in some order x1, x2, ..., xN, where xi is the card at the ith position.

Now she sequentially performs S double shuffles using the shuffle machine described above. After that, the cards are arranged in some final order p1, p2, ..., pN which Alice reveals to Bob, together with the number S. Bob‘s task is to guess the order x1, x2,
..., xN in which Alice originally put the cards just before giving them to the shuffle machine.

Input

The first line of the input contains two integers separated by a single blank character : the odd integer N, 1 <= N <= 1000, the number of cards, and the integer S, 1 <= S <= 1000, the number of double shuffle operations.

The following N lines describe the final order of cards after all the double shuffles have been performed such that for each i, 1 <= i <= N, the (i+1)st line of the input file contains pi (the card at the position i after all double shuffles).

Output

The output should contain N lines which describe the order of cards just before they were given to the shuffle machine.

For each i, 1 <= i <= N, the ith line of the output file should contain xi (the card at the position i before the double shuffles).

Sample Input

7 4

6

3

1

2

4

7

5

Sample Output

4

7

5

6

1

2

3

Source

CEOI 1998

题目大意:

第i个位置的牌是a[i],一次交换后第i个位置的牌变成a[a[i]]。序列所有位置经过一次交换为一次交换,

已知交换m次之后的序列,求原先序列

思路:想了一天,一直没明白什么意思,晚上才想明白。题目大意如上,不过需要注意的是 只能在

原有序列的基础上得到新的序列,而不能直接将原序列进行交换。

比如:              4 7 5 6 1 2 3

进行一次变换    6 3 1 2 4 7 5

而不能直接将原来第i个位置的牌改变,不能变成 6 3 1 2 6 3 5

意思就是说新的序列式在原有序列的基础上,在交换的过程中没有改变原有序列的值,从而得到一个

新的序列。

现在我们考虑变换次数和原先序列的关系

考虑                 4 7 5 6 1 2 3

进行一次变换    6 3 1 2 4 7 5

进行两次变换    7 1 6 3 2 5 4

进行三次变换    4 7 5 6 1 2 3

原序列在第三次变换的时候出现了循环

考虑一般情况。因为原序列为1~N个不同的数,则序列能构成至少一个置换群,则经过多次变换后肯定

会出现循环,现在我们求出置换的循环节,已知新的序列,和进行交换的次数,则再进行res - s % res

次交换即可得到原序列。//res为循环节,s为给出的变换次数

#include <stdio.h>
#include <string.h>

int Array[1010],ArrayA[1010],ArrayB[1010];

void GetNext(int n)
{
    for(int i = 1; i <= n; i++)
        ArrayB[i] = ArrayA[ArrayA[i]];
    for(int i = 1; i <= n; i++)
        ArrayA[i] = ArrayB[i];
}

bool IsSame(int n)
{
    for(int i = 1; i <= n; i++)
        if(ArrayB[i]!=Array[i])
            return false;
    return true;
}
int main()
{
    int n,s;
    while(~scanf("%d%d",&n,&s))
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&Array[i]);
            ArrayA[i] = Array[i];
        }
        int res;
        for(res = 1;;res++)
        {
            GetNext(n);
            if(IsSame(n))
                break;
        }
        int m = res - s % res;
        int num = 0;
        while(num < m)
        {
            GetNext(n);
            num++;
        }
        for(int i = 1; i <= n; i++)
            printf("%d\n",ArrayB[i]);
    }
    return 0;
}
时间: 2024-10-28 04:33:21

POJ1721_CARDS【置换群】的相关文章

[BZOJ 1025] 游戏 置换群 背包DP

题意 对于一个 $n$ 阶置换群 $A$ , 它的循环节大小分别为 $a_1, a_2, ..., a_m$ , 则有 $\sum_{i = 1} ^ m a_i = n$ . 定义 $f(A)$ 为它的所有循环节的最小公倍数, 即 $f(A) = [a_1, a_2, ..., a_m]$ . 求在所有 $n$ 阶置换群中, $f(A)$ 有多少种取值. $n \le 1000$ . 分析 判断 $K$ 可不可取. $K = \prod_{i = 1} ^ r {s_r} ^ {t_r}$ 可

【置换群】【枚举约数】hdu6038 Function

把b数组的所有置换群求出来,用数组记录一下每个大小所出现的次数. 然后求a的置换群,对每个置换群求能被其整除的b的置换群的大小总和(只有这些才能满足构造出一个f,且不自相矛盾),然后把它们全都乘起来就是答案. #include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define MOD 1000000007ll int n,m,a[100010],b[100010],zu; boo

hdu5338(2015多校4)--ZZX and Permutations(置换群)

题目链接:点击打开链接 题目大意:给出一个序列,分成若干个置换群,要求最终的序列的字典序最大. 要求字典序最大,那么从1开始向后遍历,尽量放较大的数 给出序列a1 a2 a3 ,,, ai   an 对于第i个数来说,可能有三种情况,第一种向前找能到达的序列的最大值ak,那么ak到ai就是一个轮换:第二种ai自身,或者是以ai结尾:第三种由i想后找,对于轮换来说,只能在i位置放ai+1,那么ai和ai+1只能构成轮换的一部分:在这三种可以放的值中选出最大值,也就是第i个位置能放的数 注意 1.当

poj3270--Cow Sorting(置换群)

题目链接:点击打开链接 题目大意:给出你n个数,要求把这n个数排列成有序的(由小到大),每次可以交换两个数,花费是这两个数的和,现在求最小的花费 置换群的入门 求出每一个轮换的圈,对于每一个轮换中,只有在自身内交换就能完成有序,而不需要和其它轮换交叉. 一个轮换的最小值temp,轮换中有num个数,轮换的总和是sum,整个序列的最小值min1 让一个轮换花费最少有两种可能 1.轮换自身交换,轮换的最小值和其他值交换num-1次,那么花费是sum-temp+(num-1)*temp 2.用全局的最

Codeforces 441D Valera and Swaps(置换群)

题意: 给定一个1~n的排列(n<=3000),输出字典序最小且次数最少的交换操作,使得操作后的排列可以通过最少m次交换得到排列[1,2,...n] Solution: 可以将排列的对应关系看做边,f[i]=i,代表自环.那么根据置换原理,图中有k个环,则需要最少n-k次交换操作得到排列[1,2...n].所以,先找出图中的环,对同一个环的位置进行标记.这样对不在同一个环的两个位置进行交换,会将两个环合并.将在同一个环内的两个位置进行交换,会将这个环分成两个环. 只需要,判断需要加环还是去环.贪

POJ 1026 置换群的k次幂问题

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

poj 3270 Cow Sorting 置换群 简单题

假设初始状态为 a:2 3 1 5 4 6 则目标状态为 b:1 2 3 4 5 6且下标为初始状态中的3 1 2 4 5 6(a[3],a[1]...) 将置换群写成循环的形式 (2,3,1),(5,4),6就不用移动了. 移动方式2种 1:选循环内最小的数和其他len-1个数交换 2:选整个序列最小的数和循环内最小的数交换,转到1,再换回来. #include<cstdio> #include<queue> #include<algorithm> #include&

poj 3270 Cow Sorting(初涉置换群)

http://poj.org/problem?id=3270 大致题意:给出n个整数,要将它们转化成递增序列,每交换其中两个数的代价是这两个数之和.问排序成功后的最小代价. 该题考察的是置换群知识.在黑书p247上有详细的讲解.总结下置换群,方便复习. 群:给定一个集合G={a,b,c...}和集合G上的二元运算 ·,如果满足封闭性,结合律,存在单位元和逆元,则成集合G在运算'·'之下是一个群. 置换:n个元素1,2,....,n之间的置换可表示为  1     2     3     ...

!HDU 4345 置换群的环长有多少种-dp

题意:置换群,问环的长度有多少种 分析: 环的长度就是每次你选择的区间长度的最小公倍数.总区间长度是n,那么这道题就是求和等于n的各个数的最小公倍数有多少种. 状态:dp[i][j]前i个质数,区间长度不超过j的最优解 转移:dp[i][j]=dp[i-1][j]+dp[i-1][j-k],k=prim[i]^1,2... 这题和上一题的dp难哭我了. 代码: #include<iostream> #include<cstdio> #include<algorithm>