由三国杀引发的扑克牌谜题

题面

这是一个由我们 hyp神犇 提出的问题
常言道: 大神看待事物的角度就是不一样, 我们hyp神犇真是 tql!!!
先%%%%%%%%%%%%%%一波, orz


在一副无大小王的扑克牌中,选7张,问有4种不同花色的概率是多少?

解答

本蒟蒻

直接二话不说一眼看穿 信竞人本命DFS 爆搜
然后......
因为可能爆栈了, 程序假死了, 毕竟没有剪枝, 搜索树的规模实在太大了

蒟蒻代码 - 1代 => 只考虑排列

#include <bits/stdc++.h>
#define re register
using namespace std;

const int choice=7; // 选牌数目
int cnt=0;  // 选出的7张牌符合要求的总数
int card[53];   // 52张 4种花色
bitset<53> used;    // 这张牌是否使用过
bool tmp[5]; // 存储对应花色的是否存在

// 深度优先搜索 => 全排列
void dfs(int k){
    if(k==choice+1){
        if(tmp[1]&tmp[2]&tmp[3]&tmp[4]) // 4种花色都有
            cnt++;  // 总数 +1
        return;
    }
    for(re int i=1;i<=52;i++){  // 每个节点 52 种情况
        if(used[i]) continue;   // 排除已选的牌
        // 记录状态
        used[i]=1;
        tmp[card[i]]=1;
        // 向下搜索
        dfs(k+1);
        // 回溯, 还原现场
        used[i]=0;
        tmp[card[i]]=0;
    }

}

int main()
{
    ios::sync_with_stdio(0);
    clock_t c1 = clock();
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
#endif
// ======================================================================
    // 预处理牌的花色
    for(re int i=1;i<=13;i++) card[i]=1;    // 花色 -> 1
    for(re int i=14;i<=26;i++) card[i]=2;   // 花色 -> 2
    for(re int i=27;i<=39;i++) card[i]=3;   // 花色 -> 3
    for(re int i=40;i<=52;i++) card[i]=4;   // 花色 -> 4
    dfs(1); // 从第一张牌开始搜索
    cout<<cnt;

// ======================================================================
end:
    cerr << "Time Used:" << clock() - c1 << "ms" << endl;
    return 0;
}

蒟蒻代码 - 2 代 => 考虑组合

#include <bits/stdc++.h>
#define re register
using namespace std;

const int choice=7; // 选牌数目
const int tot=133784560;
int cnt=0;  // 选出的7张牌符合要求的总数
int card[53];   // 52张 4种花色
int chosen[8];
bool tmp[5];

// 深度优先搜索 => 全排列
void dfs(int k,int cur){
    if(k==choice+1){
        memset(tmp,0,sizeof(tmp));
        for(re int i=1;i<=7;i++) tmp[chosen[i]]=1;
        if(tmp[1]&tmp[2]&tmp[3]&tmp[4]) // 4种花色都有
            cnt++;  // 总数 +1
        return;
    }
    for(re int i=cur;i<=52;i++){
        chosen[k]=card[i];
        dfs(k+1,i+1);
    }

}

int main()
{
    ios::sync_with_stdio(0);
    clock_t c1 = clock();
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
#endif
// ======================================================================
    // 预处理牌的花色
    for(re int i=1;i<=13;i++) card[i]=1;    // 花色 -> 1
    for(re int i=14;i<=26;i++) card[i]=2;   // 花色 -> 2
    for(re int i=27;i<=39;i++) card[i]=3;   // 花色 -> 3
    for(re int i=40;i<=52;i++) card[i]=4;   // 花色 -> 4
    dfs(1,1); // 从第一张牌开始搜索
    cout<<setprecision(20)<<fixed<<(double)cnt/tot;

// ======================================================================
end:
    cerr << "Time Used:" << clock() - c1 << "ms" << endl;
    return 0;
}

正解(炸毛君打钱)

分类讨论
根据7张牌来自哪个花色分类讨论

\[4+1+1+1 \Rightarrow 4 \times C_{13}^4 \times 13^2 \\ 3+2+1+1 \Rightarrow 4 \times C_{13}^3 \times 3 \times C_{13}^2 \times 13^2 \\ 2+2+2+1 \Rightarrow 4 \times C_{13}^1\times C_{13}^2 \times C_{13}^2\times C_{13}^2\\ \]

所以
答案:

\[Ans=\frac{(4 \times C_{13}^4 \times 13^2)+(4 \times C_{13}^3 \times 3 \times C_{13}^2 \times 13^2)+(4 \times C_{13}^1\times C_{13}^2 \times C_{13}^2\times C_{13}^2)}{C_{52}^7}\\ \approx 0.569578044 \]

posted @ 2021-10-12 09:32  不爱喝橙子汁的橙子  阅读(159)  评论(0编辑  收藏  举报