博主头像
mxd's Blog

"The quieter you become,the more you are able to hear."

C++洗牌 题解

原题目&题目要求:

题目描述

小明把 n (n 为偶数)张牌按编号顺序 1, 2, 3, ..., n 排成一堆,然后开始洗牌。一次洗牌的过程如下:
1. 对于一堆牌编号为 a1, a2, ..., an,首先将牌分成均匀的两堆:
a1, a2, ..., am和am+1, am+2, ..., an (其中m=n/2)
2. 然后按顺序交叉插入:
a1,am+1,a2,am+2,...,am,an
洗牌过程总共重复了 k 次,请你编程帮助小明模拟洗牌的过程。
例如 n = 6,初始时牌堆中牌的编号为 1, 2, 3, 4, 5, 6。
首次洗牌时,会将牌分成 1, 2, 3 和 4, 5, 6 两堆,交叉插入后的结果为 1, 4, 2, 5, 3, 6。
再次洗牌,会将牌分成 1, 4, 2 和 5, 3, 6 两堆。交叉插入后得到 1, 5, 4, 3, 2, 6。

输入格式

正整数 n (牌的数量), k (洗牌的次数), i (牌的位置)。1 ≤ n, k ≤ 1,000,1 ≤ i ≤ n, 保证 n 是偶数。

输出格式

n 张牌洗牌 k 次后,牌堆中第 i 张牌的编号。

输入样例

6 2 5

         

输出样例         

2

以下是我的代码,请勿抄袭!


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#define uns using namespace std
#define problem_e main
#define ok return 0
uns;
typedef long long LL;
const int maxn=1005;
int problem_e()
{
    LL n,k,m,a[maxn],b[maxn];
    //我感觉,i作为for的次数flag习惯了
    //所以这里把题目中要输入的i,换为了m
    cin>>n>>k>>m;
    //换成m,后面for里面就可以用i作为for的次数flag
    for(int i=0;i<n;i++)
    {
        a[i]=i+1;
    }    
    while(k--)//这里我感觉使用while要比for好一些,可以直接让k去--
    {    
        LL j=0;
        for(int i=0;i<n/2;i++)
        {    
            b[j++]=a[i];
            b[j++]=a[i+n/2];    
        }
        for(int i=0;i<n;i++)
        {
            a[i]=b[i];
        }
        //这两个for对应题目当中的
        //1. 对于一堆牌编号为 a1, a2, ..., an,首先将牌分成均匀的两堆:
        //a1, a2, ..., am和am+1, am+2, ..., an (其中m=n/2)
        //2. 然后按顺序交叉插入:
        //a1,am+1,a2,am+2,...,am,an 
    }
    cout<<b[m-1];
    ok;
    //其实这道题还是特别简单,只需要摸清顺序就ok
}
//123456 -> 123/456 -> 142536 -> 142/536 -> 154326 
//求第五个数,第五个数就是2
//https://blog.mxdyeah.top/?id=8    题解


C++洗牌 题解
https://blog.mxdyeah.top/mxdyeah_blog_post/8.html
本文作者 mxdyeah
发布时间 2023-07-24
许可协议 CC BY-NC-SA 4.0
发表新评论