玩扑克
题目链接
https://www.luogu.com.cn/problem/P2021
题意
将n张扑克牌经过“每次把最上方的牌放在牌底,然后把下一张扑克牌进行输出”的洗牌操作后,最后输出洗好的为1-n序列的扑克牌,求该扑克牌的原序列。
思路
- 可以先利用案例给出的输出模拟一下如何走到洗好后的牌的序列,找到洗牌前后每个牌数下标(索引)的变换规律
- 利用1-n进行倒推,将1-n看成是洗牌前的序列,使用抽最上面的牌到最下面,下一张出牌的规则推出最后输出的牌的序列,此时的洗牌前后的下标(索引)的变换规律和刚才的规律是一致的。
- 可以发现洗牌后的序列对应的就是洗牌前的牌数
坑点
- 无,就是绕
实现步骤
- 利用队列——先进先出
- 定义两个数组,一个数组a[i]储存洗牌后的牌,一个数组b[i]储存洗牌前的牌
- 定义队列q,将1-n使用队列的方法进行入队,再将第一个元素放到队列q的末尾,并将其所在的初始位置删除,此时2就是第一个数(定义一个m,使其初始值为1,每次将前面的牌抽到牌底后,m就+1,得到的值也就是此时队列的第一个值)。
代码
#include <bits/stdc++.h>
using namespace std;
int a[1000010],b[1000010];
int main()
{
queue<int> q;
int n;
int m=1;
cin>>n;
for(int i=1;i<=n;i++)
{
q.push(i);
}
while(!q.empty())
{
q.push(q.front());
q.pop();
a[m++]=q.front();
q.pop();
}
for(int i=1;i<=n;i++)
{
b[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
cout<<b[i]<<" ";
}
return 0;
}