Card Trick

题目连接

题意:

按一定的顺序的卡片(标有数字)叠放在一起,第一次从最上面拿一张放到最后,此时拿走最 上面的卡片放在一旁,然后再从最上面拿走两张牌放到最下面,此时拿走最上面的卡片也放到一旁,以此次下去

问题:

最开始的顺序应该如何放置,按照这个规则,把卡片拿完之后在一旁的卡片刚好是按照从小到大的顺序排放的,

分析:

举个例子:有一个数字a按照一定的规则(假如这个规则是减去2)得到数字7,问题:这个数字是几?很明显用7+2既是原来的数字a;因为7通过逆规则可以得到a,加2是减2的逆规则

同理:此题解法就是找到题目所给规则的逆规则,根据逆规则就可由结果推出原来的序列

但是 但是 但是:此题的规则很麻烦,找出逆规则更不容易,该咋办!!
卡片原来的顺序可以用数组存下来经过题目所给的规则(不是逆规则)后得到顺序的卡片
如果拿已经有序的卡片也用同规则进行变换,得到的顺序用数组保存下来,根据上述可以知道这个保的
顺序,与正确的顺序相比此数组的下标和数组的值是相反的。
假如正确的顺序是 a[1]=2 a[2]=1 a[3]=4 a[4]=3
那么得到的顺序是 a[2]=1 a[1]=2 a[4]=3 a[3]=4
所以在最后处理的时候 把数组的值当做下标 把下标当做值即可

#include<stdio.h>
#include<string.h>
#include<map>
#include<string>
#include<algorithm>
#include<iostream>
#include<set>
#include<queue>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int m=0;
        scanf("%d",&m);
        queue<int>q;
        for(int i=0; i<m; i++)
        {
            q.push(i+1);//已知正序
        }
        int k=1;
        int v[m+1];
        while(!q.empty())
        {
            for(int i=1; i<=k; i++)//题目规则
            {
                int b=q.front();
                q.pop();
                q.push(b);
            }
            int c=q.front();
            q.pop();
            v[c]=k;//下标和值相反
            k++;
        }
        printf("%d",v[1]);
        for(int i=2; i<=m; i++) 
            printf(" %d",v[i]);
        printf("\n");
    }
    return 0;
}
posted @ 2017-04-14 19:13  -梦里不知身是客  阅读(288)  评论(0编辑  收藏  举报