跳转至

BISHI17 纸牌游戏

简单通过率 37.38%python3样例通过牛客 AC

牛客原题  源码

讲解章节模拟

一句话

双方各两张牌,翻牌顺序随机,数出 Alex 获胜的顺序数。

解题思路

这题考什么

先把「随机」这个词翻译成「有限种等可能的情形」,再暴力枚举。 Alex 手上两张牌,先翻哪张有 2 种选择;Bob 同理 2 种; 两人的选择互不影响,所以「翻牌顺序」一共 2 * 2 = 4 种, 每种把两个回合模拟一遍、看 Alex 是否赢的回合更多即可。 这题问的是顺序的数量而不是概率,所以答案就是这 4 种里合格的个数, 上界必然是 4(样例第 3 组的答案正是 4)。

zip(a, b) 恰好把两人各自的出牌序列按回合对齐:第 k 对就是第 k 回合。

数据规模与复杂度

t <= 1e4 组,每组 4 种顺序 * 2 个回合,总复杂度 O(t)。 每组固定 4 个整数、行长一致,所以可以直接用 data[1 + 4i : 5 + 4i] 定位, 不需要额外的游标变量。

坑在哪

  1. 单个回合比大小时,相等是双方都不得分,不是各得一分, 所以要分别数出 win 和 lose,不能用「win >= 1」之类的近似判断;
  2. 「赢得回合数更多者获胜」是严格更多:一胜一负、两回合都打平, 都算无人获胜,不能算 Alex 赢。判断必须是 win > lose;
  3. 统计的是顺序数量,牌面重复也照样算不同顺序。 10 10 2 2 里 Alex 的两种「顺序」牌面完全相同,但仍然各算一种, 答案是 4 而不是 1;
  4. 题面给出的牌是 a1,a2 属于 Alex、b1,b2 属于 Bob, 而示例说明里的叙述把两人的牌讲反了,以输入描述为准。

样例复核

3 8 2 6:Alex 持 3、8,Bob 持 2、6。四种顺序中 (3,8) 对 (2,6) 赢两局、(8,3) 对 (6,2) 赢两局,另两种各一胜一负, 合计 2 种,与样例一致。

参考实现

solutions/BISHI17.py
import sys

data = sys.stdin.buffer.read().split()
t = int(data[0])
out = []
for i in range(t):
    a1, a2, b1, b2 = map(int, data[1 + 4 * i:5 + 4 * i])   # 每组固定四个数
    cnt = 0
    # 枚举 Alex 的两种出牌顺序 x Bob 的两种出牌顺序,共 4 种翻牌顺序
    for a in ((a1, a2), (a2, a1)):
        for b in ((b1, b2), (b2, b1)):
            win = sum(x > y for x, y in zip(a, b))         # Alex 赢下的回合数
            lose = sum(x < y for x, y in zip(a, b))        # Bob 赢下的回合数
            if win > lose:                                 # 严格更多才算 Alex 获胜
                cnt += 1
    out.append(cnt)
sys.stdout.write("\n".join(map(str, out)) + "\n")
[:octicons-arrow-left-16: BISHI16](BISHI16.md) [BISHI18 :octicons-arrow-right-16:](BISHI18.md)