完美洗牌问题学习笔记

2023-12-13 04:25:49

问题背景

完美洗牌:一副 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?(modm?1)
转为数学计算公式
( m ? 1 ) ∣ 2 n ? m 2 2 n ? m 2 = ( m ? 1 ) k , k ∈ z , n > = m 2 (m - 1) | 2^n - \frac{m}{2} \\ 2^n - \frac{m}{2} = (m - 1)k, k \in z, n >= \sqrt{\frac{m}{2}} (m?1)2n?2m?2n?2m?=(m?1)k,kz,n>=2m? ?

编程计算

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

    m = 52
    b = m // 2
    c = m - 1
    n = math.floor(math.sqrt(b))
    while True:

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

## res:
## success 7

可以求得在 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 时, 再也找不到解

文章来源:https://blog.csdn.net/qq_34727886/article/details/134807255
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。