标签:des style blog http color io os 使用 ar
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 1448 | Accepted: 773 |
Description
Input
Output
Sample Input
7 4 6 3 1 2 4 7 5
Sample Output
4 7 5 6 1 2 3
Source
Mean:
剀剀和凡凡有N张牌(依次标号为1,2,……,N)和一台洗牌机。假设N是奇数。洗牌机的功能是进行如下的操作:对所有位置I(1≤I≤N),如果位置I上的牌是J,而且位置J上的牌是K,那么通过洗牌机后位置I上的牌将是K。
剀剀首先写下一个1~N的排列ai,在位置ai处放上数值ai+1的牌,得到的顺序x1, x2, ..., xN作为初始顺序。他把这种顺序排列的牌放入洗牌机洗牌S次,得到牌的顺序为p1, p2, ..., pN。
现在,剀剀把牌的最后顺序和洗牌次数告诉凡凡,要凡凡猜出牌的最初顺序x1, x2, ..., xN。
analyse:
刚开始搞置换群,看得云里雾里的,还好看到了潘震皓的《置换群快速幂运算 + 研究与探讨》,讲的很清楚,而且很符合ACM的出题习惯。
很显然,这是一题典型的置换群问题,一副扑克就是一个置换,而对于每次的操作,我们可以看作置换的平方运算,题目说n为奇数,这就保证了在进行置换平方运算的过程中不会出现分裂,那么我们就可以使用置换群的快速幂来做了。
进行2*x次运算就可,当然其中有一个剪枝,将O(n^2+logs)的时间复杂度变为了O(n+logs)了,十分经典。
Time complexity:O(n+logs)
Source code:
// Memory Time
// 1347K 0MS
// by : Snarl_jsb
// 2014-09-11-20.34
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<climits>
#include<cmath>
#define N 1010
#define LL long long
using namespace std;
int a[N],b[N],c[N],n,m;
int work()
{
int j;
int cnt=0;
while(1)
{
for(int i=1;i<=n;i++)
b[i]=c[c[i]];
cnt++;
for(j=1;j<=n;j++)
if(b[j]!=a[j])
break;
if(j>n)break;
for(int i=1;i<=n;i++)
c[i]=b[i];
}
return cnt;
}
int main()
{
// freopen("C:\\Users\\ASUS\\Desktop\\cin.cpp","r",stdin);
// freopen("C:\\Users\\ASUS\\Desktop\\cout.cpp","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
c[i]=a[i];
b[i]=a[i];
}
int cnt=work();
m%=cnt;
m=cnt-m;
while(m--)
{
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 CARDS (洗牌机)
标签:des style blog http color io os 使用 ar
原文地址:http://www.cnblogs.com/acmer-jsb/p/3967226.html