由三国杀引发的扑克牌谜题
题面
这是一个由我们 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
\]