我们不难发现,他们选的五个数必定会有一个是 #
,未知的。我们只用枚举高桥和青木两人未知的数的值,再来判断高桥是否能赢就行了。
我们用 s u m a l l sum_{all} sumall 来表示他们两人未知的数一共的可能选法,用 s u m w i n sum_{win} sumwin 来表示高桥在其中获胜的数量,则答案就是 s u m w i n s u m a l l \frac{sum_{win}}{sum_{all}} sumallsumwin。我们可以先用 s u m t sum_t sumt 来表示高桥除了未知数的得分,也就是 ∑ i = 1 9 i × 1 0 c i \sum_{i=1}^9 i \times 10^{c_i} ∑i=19i×10ci,其中 c i c_i ci 是数字为 i i i 高桥的牌的数量, s u m s sum_s sums 表示青木的得分,求法和高桥的一样。对于每一个填入未知数的方案,我们判断高桥是否能赢,如果能赢,将 s u m w i n sum_{win} sumwin 自增。而 s u m a l l sum_{all} sumall 是等于 ( k × 9 − 8 ) × ( k × 9 − 9 ) (k\times 9-8)\times (k\times 9-9) (k×9−8)×(k×9−9),其实就是利用到了组合数学。 k × 9 k\times 9 k×9 是一共拥有的牌的数量,减去已经使用的八张,高桥的选法就是 k × 9 − 8 k\times 9-8 k×9−8。青木的就刚好是高桥的减去一,既为 k × 9 − 9 k\times 9-9 k×9−9。最后相乘就可以求出 s u m a l l sum_{all} sumall。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int k;
string s, t;
int bjs[1005], bjt[1005];//分别表示高桥与青木使用第i种牌的数量
int sums, sumt;
signed main() {
cin >> k;
cin >> s >> t;
for (int i = 0; i <= 4; i++) {
if (s[i] != '#') {
bjs[s[i] - '0']++;//让高桥的第s[i]种牌的数量增加
}
if (t[i] != '#') {
bjt[t[i] - '0']++;//让青木的第t[i]种牌的数量增加
}
}
for (int i = 1; i <= 9; i++) {
sums += i * pow(10, bjs[i]);//求出高桥的除了未知数的得分
sumt += i * pow(10, bjt[i]);//求出青木的除了未知数的得分
}
int sum = (k * 9 - 8) * (k * 9 - 9);//求总数
int ans = 0;
for (int i = 1; i <= 9; i++) {
if (bjs[i] + bjt[i] + 1 > k) {//判断是否能选
continue;
}
int op = sums + 9 * i * pow(10, bjs[i]);//算出新的分数
bjs[i]++;
for (int j = 1; j <= 9; j++) {
if (bjs[j] + bjt[j] + 1 > k) {/判断是否能选
continue;
}
int po = sumt + 9 * j * pow(10, bjt[j]);//算出新的分数
if (op > po) {//合法
ans += (k - bjs[i] - bjt[i] + 1) * (k - bjt[j] - bjs[j]);//将统计增加
}
}
bjs[i]--;
}
printf("%.8lf\n", ans * 1.0 / sum);//输出答案
return 0;
}