题目描述
剀剀和凡凡有N张牌(依次标号为1,2,……,N)和一台洗牌机。假设N是奇数。洗牌机的功能是进行如下的操作:对所有位置I(1≤I≤N),如果位置I上的牌是J,而且位置J上的牌是K,那么通过洗牌机后位置I上的牌将是K。
剀剀首先写下数值1,2,……,N的一个随机排列:a1, a2, …, aN。然后他这样来排列牌的顺序:位置ai 放置牌ai+1, (对1≤i≤N-1),而aN 放置牌a1。这样排列后,牌的顺序就为x1, x2, …, xN。然后,他把这种顺序排列的牌放入洗牌机洗牌S次,得到牌的顺序为p1, p2, …, pN。现在,剀剀把牌的最后顺序和洗牌次数告诉凡凡,要凡凡猜出牌的最初顺序x1, x2, …, xN。
输入输出格式
输入格式:
第一行为整数N和S。1≤N≤1000,1≤S≤1000。第二行为牌的最终顺序p1, p2, …, pN。
输出格式:
为一行,即牌的最初顺序x1, x2, …, xN。
输入输出样例
输入样例#1: 复制
5 2
4 1 5 3 2
输出样例#1: 复制
2 5 4 1 3
就是一道找循环节的问题:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,s,a[2001],b[2001],c[2001];
bool judge(int *A,int *B)
{
for (int i=1; i<=n; i++)
if (A[i]!=B[i]) return false;
return true;
}
int main()
{
scanf("%d%d",&n,&s);
for (int i=1; i<=n; i++) scanf("%d",&a[i]),b[i]=a[i];
int total=0;//循环节的长度
while (1)
{
for (int i=1; i<=n; i++)
c[i]=b[b[i]];
total++;
if (judge(c,a)) break;
for (int i=1; i<=n; i++)
b[i]=c[c[i]];
total++;
if (judge(b,a)) break;
}
total=total-s%total;//num向后数几个 必须要%%%%!
int k=0;
for (int i=1; i<=n; i++) b[i]=a[i];//漏掉了这里
while (1)
{
for (int i=1; i<=n; i++) c[i]=b[b[i]];
k++;
if (k==total)
{
for (int i=1; i<=n; i++) printf("%d ",c[i]);
return 0;
}
for (int i=1; i<=n; i++) b[i]=c[c[i]];
k++;
if (k==total)
{
for (int i=1; i<=n; i++) printf("%d ",b[i]);
return 0;
}
}
return 0;
}
/*
5 2
4 1 5 3 2
2 5 4 1 3
*/