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;
}
梦里不知身是客,一晌贪欢。