嘘~ 正在从服务器偷取页面 . . .

模拟赛题讲解[23]


模拟赛题讲解[23]

来自 s_r_f 2023-08-02 noi.ac #3191

题目描述

一副牌,有 \(4\) 种花色(从 \(1\) 开始标号),每种花色各 \(13\) 张牌,点数从 \(1-13\),一共 \(52\) 张牌。

定义五张牌组成的集合的大小比较规则如下:(和某种扑克规则有出入,请仔细阅读

  1. 同花顺 : 同种花色的,点数形如 \(x,x+1,x+2,x+3,x+4\) 的五张牌;
  2. 四条 : 四张点数相同的牌;
  3. 葫芦 : 三张点数为 \(x\) 的牌,带上另一个点数 \(y(y\neq x)\) 的一个对子;
  4. 同花 : 五张花色相同的牌;
  5. 顺子:点数形如 \(x,x+1,x+2,x+3,x+4\) 的五张牌;
  6. 三条:三张点数为 \(x\) 的牌。
  7. 两对:有两个不同点数的对子, 即点数形如 \(x,x,y,y\) 的四张牌;
  8. 一对:一个对子,即点数形如 \(x,x\) 的两张牌;
  9. 高牌:最大单牌。

\(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;
}

题外话

搞了半天还是来上这最后一次集训了啊。

感叹,去年的我还是怀揣梦想的来到这,如今我却是拖着“残破的身躯”苦苦挣扎了。

不过,还是有希望的。


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录