poj 1721 CARDS(置换)

http://poj.org/problem?id=1721

大致题意:原始序列通过洗牌机洗牌s次后变为当前序列,已知当前序列,求原始序列。

置换群快速幂运算 研究与探讨中最后有详解,有两种解法,一种是求出置换的长度a(即一副牌洗a次后变回原来的位置),现已知原始序列置换s次变为当前序列,那么当前序列再置换a-s次就是原始序列了。求a就是直接模拟每个置换的过程,直到某序列与当前序列相等。另一种是置换的开方,相当于原始序列的2^s幂是当前序列,将当前序列开2^s次方便是原始序列。

第二种方法暂时还不会,先贴第一种。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
#define PI acos(-1.0)
using namespace std;

const int maxn = 1010;
const int INF = 0x3f3f3f3f;
int n,s;
int a[maxn],b[maxn],c[maxn];

//求置换的长度a
int solve()
{
	int cnt = 0,i;
	while(1)
	{
		for(i = 1; i <= n; i++)
			b[i] = c[c[i]];
		cnt++;
		for(i = 1; i <= n; i++)
			if(a[i] != b[i])
				break;

		if(i > n)
			break;
		for(i = 1; i <= n; i++)
			c[i] = b[i];
	}
	return cnt;
}

int main()
{
	while(~scanf("%d %d",&n,&s))
	{
		for(int i = 1; i <= n; i++)
		{
			scanf("%d",&a[i]);
			b[i] = a[i];
			c[i] = a[i];
		}

		int cnt = solve();
		s %= cnt;
		s = cnt - s;
		while(s--)
		{
			for(int i = 1; i <= n; i++)
				b[i] = a[a[i]];
			for(int i = 1; i <= n; i++)
				a[i] = b[i];
		}
		for(int i = 1; i <= n; i++)
			printf("%d\n",b[i]);

	}
	return 0;
}

poj 1721 CARDS(置换)

时间: 2024-10-27 05:58:22

poj 1721 CARDS(置换)的相关文章

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

[POJ 1721]CARDS

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

poj 2369 Permutations 置换水题

找循环节求lcm就够了,若答案是12345应该输出1,被坑了下. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> using namespace std; #define INF 0x3FFFFFF #define MAXN 2222 #define eps 1e-6 i

poj 3590(dp 置换)

题目的意思是对于序列1,2,...,n.要你给出一种字典序最小的置换使得经过X次后变成最初状态,且要求最小的X最大. 通过理解置换的性质,问题可以等价于求x1,x2,..,xn 使得x1+x2+...+xk=n,且GLM(x1,x2,...,xn)最大. 这个就用dp来做,首先求出100内的所有素数记录为prime[1] 到 prime[25]. 状态:dp[i][j] 表示花费了i,且已经使用prime[1] 到 prime[j],的最大值. 转移方程:因为要求最大值,单纯的用素数的积并不能得

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 1721

好像不需要用到开方什么的... 可以知道,一副牌即是一个循环,那么,由于GCD(L,K)=1,所以一次洗牌后,亦是一个循环.其实,K次洗牌等于是T^(2^K)了.既然是循环,必定有周期.那么,周期是多少呢?以例子为例:1->4->6->2->7->3->5.其实对于第一个数(从零始)4,总会有先后移了2^a次方而回到原点,此时就是一个周期了.即是求2^a=1(mod n).求出最小的a即可知道周期.s%a=t.那么,即是差a-t个状态就可以回到初始的了. #includ

觉得一篇讲SPFA还不错的文章

我觉得他整理的有一些乱,我都改成插入代码了,看的顺眼一些 转载自http://blog.csdn.net/juststeps/article/details/8772755 下面的都是原文: 最短路径 之 SPFA算法 http://hi.baidu.com/southhill/item/ab26a342590a5aae60d7b967 求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了.最熟悉的无疑是Dijkstra,接着是Bellman-Ford,它们都可以求出由

HDU 1535 &amp;&amp; POJ 1511 Invitation Cards (SPFA 模板 + 反向建图)

Invitation Cards HDU: Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) POJ: Time Limit: 8000 MS     Memory Limit: 262144 K       Problem Description In the age of television, not many people attend theater performa

POJ 1511 Invitation Cards

题目来源:http://poj.org/problem?id=1511 题目很长,花了不少时间才理解题意,目的就是为了求出来回两次最小路径(即为本题的差旅费)之和, 第一次从CCS(1)出发到各个点路径最小,SPFA算法没得说,回来时终点是确定的都是CCS(1),相当于把路 径反过来,即把有向图去反方向,又是从1出发到各个点路径最小,再用一个SPFA.注意ans要用long long 不然也WA,这个地方WA了好几次,虽然更改后AC了,但还是不明白,题目明明写了smaller than 1000