模拟赛题讲解[23]
来自 s_r_f 2023-08-02 noi.ac #3191
题目描述:
一副牌,有 $4$ 种花色(从 $1$ 开始标号),每种花色各 $13$ 张牌,点数从 $1-13$,一共 $52$ 张牌。
定义五张牌组成的集合的大小比较规则如下:(和某种扑克规则有出入,请仔细阅读)
- 同花顺 : 同种花色的,点数形如 $x,x+1,x+2,x+3,x+4$ 的五张牌;
- 四条 : 四张点数相同的牌;
- 葫芦 : 三张点数为 $x$ 的牌,带上另一个点数 $y(y\neq x)$ 的一个对子;
- 同花 : 五张花色相同的牌;
- 顺子:点数形如 $x,x+1,x+2,x+3,x+4$ 的五张牌;
- 三条:三张点数为 $x$ 的牌。
- 两对:有两个不同点数的对子, 即点数形如 $x,x,y,y$ 的四张牌;
- 一对:一个对子,即点数形如 $x,x$ 的两张牌;
- 高牌:最大单牌。
这 $9$ 种牌型的大小顺序是 同花顺 > 四条 > 葫芦 > 同花 > 顺子 > 三条 > 两对 > 一对 > 高牌,牌型按照从大到小的顺序,从 $1$ 开始编号。
小 A 手里有 $2$ 张牌,场上有 $3$ 张公共牌。他的对手手里有两张对他不公开的牌 (这 $7$ 张牌都必须来源于同一副牌,所以不会出现两张点数和花色都一样的牌)。
小 A 的五张牌集合是他手里的牌和公共牌的并集。对手也一样。
现在他想知道,在已知这五张牌的情况下,小 A 的对手拿到每种牌型的种类数。
牌型只取最大的一种,例如一个集合里有葫芦,那么就不记三条 / 两对 / 一对的出现次数。
输入格式:
输入 $5$ 行,每行两个整数 $a_i,b_i$ 按顺序分别表示第 $i$ 张牌的点数和花色。
其中,前三张牌为公共牌,后两张牌为小 A 的手牌。
输出格式:
输出一行, 9 个整数,表示小 A 的对手拿到每种牌型的种类数。
输入样例1:
9 1
10 1
11 1
12 1
13 1
输出样例1:
1 0 0 27 36 9 27 396 585
输入样例2:
9 2
11 2
11 1
5 4
5 1
输出样例2:
0 1 9 0 0 84 187 800 0
输入样例3:
4 1
8 1
7 1
13 4
6 4
输出样例3:
1 0 0 44 11 9 27 396 593
样例解释:
样例 1 解释:输入是一个同花顺。
对手是同花顺的情况只有 1 种 (唯一的可能是 7 1 和 8 1 两张牌).
因为公共牌没有对子,所以不存在四条和葫芦
同花有 C(8,2) = 28 种,去掉成顺的一种有 27 种;
…
形成 9/10/11 三条:各 3 种,一共 9 种;
形成 9,10/9,11/10,11 两对:各 9 种,一共 27 种
…
样例 2 和样例 3,是对手可能有四条 / 同花顺的例子.
数据范围:
保证输入是合法输入,即:花色在集合 $\{1,2,3,4\}$ 中,点数在集合 $\{1,2,3,4,5,6,7,8,9,10,11,12,13\}$ 中,输入中不存在相同的两张牌。
题解:
考虑枚举所有可能的牌,不超过 $52\times 52$ 种,然后对于每种情况按顺序检验就好了
代码虽然复杂,但还是很简单的,只要按着题面写就好了(虽然全场就只对了这一道。)
时间复杂度 $\mathcal{O}(\mathrm{ok})$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())
struct node { int x,tp; void r() { cin >> x >> tp; } };
bool operator==(node a, node b) { return (a.x == b.x && a.tp == b.tp); }
bool operator!=(node a, node b) { return (a.x != b.x || a.tp != b.tp); }
bool cmp1(node a, node b) { return a.x == b.x ? a.tp < b.tp : a.x < b.x; } // x, tp
bool cmp2(node a, node b) { return a.tp == b.tp ? a.x < b.x : a.tp < b.tp; } // tp, x
node a[10], b[10]; int ans[15];
bool check(node x) {
for(int i = 1; i <= 5; i++) {
if(x == b[i]) return false;
} return true;
}
void debug() { for(int i = 1; i <= 5; i++) cout << '(' << a[i].x << ' ' << a[i].tp << ')' << " \n"[i == 5]; }
void solve()
{
bool ok = 1; sort(a + 1, a + 1 + 5, cmp1);
for(int i = 2; i <= 5; i++)
if(!(a[i].tp == a[i - 1].tp && a[i].x == a[i - 1].x + 1)) ok = 0;
if(ok) { ++ans[1]; return; } else ok = 1;
if(a[1].x == a[2].x && a[2].x == a[3].x && a[3].x == a[4].x) { ++ans[2]; return; }
else if(a[2].x == a[3].x && a[3].x == a[4].x && a[4].x == a[5].x) { ++ans[2]; return; }
if(a[1].x == a[2].x && a[2].x == a[3].x && a[4].x == a[5].x) { ++ans[3]; return; }
else if(a[1].x == a[2].x && a[3].x == a[4].x && a[4].x == a[5].x) { ++ans[3]; return; }
sort(a + 1, a + 1 + 5, cmp2);
for(int i = 2; i <= 5; i++) if(!(a[i].tp == a[i - 1].tp)) ok = 0;
if(ok) { ++ans[4]; return; } else ok = 1;
sort(a + 1, a + 1 + 5, cmp1);
for(int i = 2; i <= 5; i++) if(!(a[i].x == a[i - 1].x + 1)) ok = 0;
if(ok) { ++ans[5]; return; } else ok = 1;
for(int i = 3; i <= 5; i++)
if(a[i].x == a[i - 1].x && a[i].x == a[i - 2].x) { ++ans[6]; return; }
if(a[1].x == a[2].x && a[3].x == a[4].x || a[2].x == a[3].x && a[4].x == a[5].x) { ++ans[7]; return; }
else if(a[1].x == a[2].x && a[4].x == a[5].x) { ++ans[7]; return; }
for(int i = 2; i <= 5; i++) if(a[i].x == a[i - 1].x) { ++ans[8]; return; }
// if(a[5].x >= max(b[1].x, b[2].x)) { ++ans[9]; return; }
// cout << a[5].x << ' ' << max(b[1].x, b[2].x) << '\n';
++ans[9];
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
for(int i = 3; i <= 5; i++) { b[i].r(); } b[1].r(); b[2].r();
for(int i1 = 1; i1 <= 13; i1++)
for(int j1 = 1; j1 <= 4; j1++)
{
a[4] = {i1, j1};
if(!check(a[4])) continue;
for(int i2 = 1; i2 <= 13; i2++)
{
for(int j2 = 1; j2 <= 4; j2++)
{
a[1] = b[3]; a[2] = b[4]; a[3] = b[5]; a[4] = {i1, j1}; a[5] = {i2, j2};
if(!(check(a[5]) && a[4] != a[5])) continue;
solve();
}
}
}
for(int i = 1; i <= 9; i++) cout << ans[i] / 2 << " \n"[i == 9];
return 0;
}
题外话:
搞了半天还是来上这最后一次集训了啊。
感叹,去年的我还是怀揣梦想的来到这,如今我却是拖着“残破的身躯”苦苦挣扎了。
不过,还是有希望的。