[HNOI2001]洗牌机

来源:互联网 发布:javascript xml dom 编辑:程序博客网 时间:2024/05/18 19:46

题目描述

剀剀和凡凡有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;}