完美洗牌问题学习笔记

文章探讨了一种扑克牌洗牌问题,描述了一种名为“完美洗牌”的过程,通过8次操作后牌堆恢复原序。文章介绍了如何计算经过n+1次洗牌恢复原序的通用算法,并展示了如何应用此算法解决不同数量的扑克牌问题,以及可能的无解情况。
摘要由CSDN通过智能技术生成

问题背景

完美洗牌:一副 52 张的排序好的扑克牌,从中间分为两半,每部分各 26 张。假设每次都分为左右两部分,然后将
右部分的牌和左部分的牌按顺序交错穿插,每张左部分牌后面加入一张右部分的,依序加入所有右部分牌。
完成一次穿插后得到新的牌堆。

一副排序好的扑克牌(52张),在完成第 8 次完美洗牌后,将得到和初始顺序一致的牌堆。

解答目标

求出一个通用算法:
给出任意数量的扑克牌,求经过多少次完美洗牌后恢复原序

数据打样分析

将扑克牌按顺序编号为 0 ~ 51,8 次完美洗牌的中间过程如下

1: [0, 26, 1, 27, 2, 28, 3, 29, 4, 30, 5, 31, 6, 32, 7, 33, 8, 34, 9, 35, 10, 36, 11, 37, 12, 38, 13, 39, 14, 40, 15, 41, 16, 42, 17, 43, 18, 44, 19, 45, 20, 46, 21, 47, 22, 48, 23, 49, 24, 50, 25, 51]

2: [0, 13, 26, 39, 1, 14, 27, 40, 2, 15, 28, 41, 3, 16, 29, 42, 4, 17, 30, 43, 5, 18, 31, 44, 6, 19, 32, 45, 7, 20, 33, 46, 8, 21, 34, 47, 9, 22, 35, 48, 10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51]

3: [0, 32, 13, 45, 26, 7, 39, 20, 1, 33, 14, 46, 27, 8, 40, 21, 2, 34, 15, 47, 28, 9, 41, 22, 3, 35, 16, 48, 29, 10, 42, 23, 4, 36, 17, 49, 30, 11, 43, 24, 5, 37, 18, 50, 31, 12, 44, 25, 6, 38, 19, 51]

4: [0, 16, 32, 48, 13, 29, 45, 10, 26, 42, 7, 23, 39, 4, 20, 36, 1, 17, 33, 49, 14, 30, 46, 11, 27, 43, 8, 24, 40, 5, 21, 37, 2, 18, 34, 50, 15, 31, 47, 12, 28, 44, 9, 25, 41, 6, 22, 38, 3, 19, 35, 51]

5: [0, 8, 16, 24, 32, 40, 48, 5, 13, 21, 29, 37, 45, 2, 10, 18, 26, 34, 42, 50, 7, 15, 23, 31, 39, 47, 4, 12, 20, 28, 36, 44, 1, 9, 17, 25, 33, 41, 49, 6, 14, 22, 30, 38, 46, 3, 11, 19, 27, 35, 43, 51]

6: [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51]

7: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51]

8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]

第 8 次开始倒着分析,初始每个数据相差 1,
第 7 次各个数据的间隔变为 2 的 1 次方;
第 6 次各个数据的间隔变为 2 的 2 次方;
第 5 次各个数据的间隔变为 2 的 3 次方;
第 4 次各个数据的间隔变为 2 的 4 次方;
第 3 次各个数据的间隔变为 2 的 5 次方(32) mod 51 = 32;
第 2 次各个数据的间隔变为 2 的 6 次方(64) mod 51 = 13;
第 1 次各个数据的间隔变为 2 的 7 次方(128) mod 51 = 26;
第 0 次各个数据的间隔变为 2 的 8 次方(256) mod 51 = 1; (原始顺序)

可见反过来分析后,经过 8 次完美洗牌后,扑克牌又变回了原始顺序,
总结上面的算法,得到模数公式如下,设需要经过 n + 1 次完美洗牌后,一副 m 张扑克牌的排序变为原始排序, m 为偶数。
2 n ≡ m 2 ( m o d m − 1 ) 2^n \equiv \frac{m}{2} \pmod{m-1} 2n2m(modm1)
转为数学计算公式
( m − 1 ) ∣ 2 n − m 2 , ( m > = 2 ) 2 n − m 2 = ( m − 1 ) k , k ∈ z , n > = log ⁡ 2 m 2 ( n > = log ⁡ 2 m − 1 ) (m - 1) | 2^n - \frac{m}{2},(m >= 2) \\ 2^n - \frac{m}{2} = (m - 1)k, k \in z, n >= \log_{2}{\frac{m}{2}} \\ (n >= \log_{2}{m} - 1) (m1)2n2m,(m>=2)2n2m=(m1)k,kz,n>=log22m(n>=log2m1)

编程计算

import math

def test():
    # 51 | 2 ** n - 26 

    m = 52
    b = m // 2
    c = m - 1
    n = math.ceil(math.log2(m) - 1)
    a = 1 << n
    
    while True:

        if (a - b) % c == 0:
            print("success", n)
            break
        n += 1
        a <<= 1

## res:
## success 7
test()

可以求得在 m 等于 52 时,n 等于 7, 即 52 张扑克牌经过 n + 1 = 8 次完美洗牌后会恢复原始排序。

拓展学习

上面的分析是基于 0 ~ 51 的编号,也就是和原始的扑克牌花色点数没有关系,任意 52 张扑克牌做了 8 次完美洗牌后,都会恢复到原始的序位。

可以将扑克牌的数量增加 8 张,相当于每种花色多了 2 张牌,这时扑克牌的总数是 60 张,套入上面的算法可以求得经过 58 次完美洗牌后,60 张牌会和未洗牌的顺序一样。

还可以深入研究的点:

  1. 什么情况下会无解
  2. 在小于 52 张的时候,什么情况无解
  3. 是否存在从某个数 x x x 开始,当扑克牌的数量 n > = x n >= x n>=x 时, 再也找不到解
  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学习MATLAB时,编写学习笔记是一种很好的方法,可以帮助您记录重要的概念、语法和技巧,以及解决问题的步骤。以下是一些关于编写MATLAB学习笔记的建议: 1. 组织结构:使用清晰的标题和分节来组织您的学习笔记。将不同的主题分成单独的部分,并使用子标题来进一步细分内容。 2. 内容概要:在每个部分或子标题下,写下该主题的概要。这样可以帮助您回顾和理解该主题的关键点。 3. 示例代码和输出:对于每个主题,包括一些示例代码和相应的输出结果。这有助于您理解和演示具体的MATLAB语法和功能。 4. 问题与解答:如果您在学习过程中遇到了一些困惑或问题,将其记录下来,并在笔记中提出并解答这些问题。这样可以帮助您深入思考并加深对该主题的理解。 5. 笔记补充:除了基本概念和语法外,您还可以添加一些额外的笔记,如最佳实践、编程技巧、常见错误等。这些额外的笔记可以提供更多的实用信息和提示。 6. 参考资料:在您的学习笔记中,包括引用的参考资料,如教程、文档、书籍或网站链接。这样,您可以随时回顾并深入研究相关的主题。 7. 总结和复习:在学习笔记的结尾,添加一个总结部分,回顾和总结您学到的重点和关键概念。此外,定期复习您的学习笔记也是加深理解和记忆的好方法。 以上是关于编写MATLAB学习笔记的一些建议。希望这对您有所帮助,并祝您在MATLAB学习过程中取得成功!如果有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值