[AHOI2001] 彩票摇奖

GitHub跳转原题关系图返回列表

把中奖号码存成集合,统计每张彩票与它的交集大小并映射到对应奖项。

OJ: luogu

题目 ID: P2550

难度:入门

标签:模拟集合python

日期: 2026-07-15 18:48

题意

给出 7 个中奖号码和 n 张彩票。每张彩票也有 7 个号码。匹配 7 个是特等奖,匹配 6 个是一等奖,依次到匹配 1 个是六等奖。输出每个奖项各有多少张彩票。

思路

题目不关心号码顺序,只关心是否出现,所以用集合最自然。

把中奖号码存成 winning。对每张彩票,把它也转成集合 ticket,两者交集:

text
winning & ticket

就是命中的号码集合。交集大小 match_count 表示命中几个号码。

输出顺序是命中 7,6,5,4,3,2,1 个,因此数组下标可以写成:

text
answer[7 - match_count] += 1

如果 match_count = 0,没有奖项,不统计。

这题是集合统计练习,正解已经直接对应题意,不创建 brute.py

Python 知识

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:用 map(int, input().split()) 读取号码。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/collections_toolkit.mdset 适合做去重和成员关系判断。
  • winning & ticket 是集合交集。
  • len(...) 得到命中号码个数。
  • print(*answer) 按空格输出七个奖项数量。

代码

python
ticket_count = int(input())
winning = set(map(int, input().split()))

answer = [0] * 7

for _ in range(ticket_count):
    ticket = set(map(int, input().split()))
    match_count = len(winning & ticket)
    if match_count > 0:
        answer[7 - match_count] += 1

print(*answer)
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

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

int win[7];      // 中奖号码
bool is_win[34]; // 标记某个号码是否中奖号码(号码范围 1~33)
int ans[8];      // ans[i] 表示匹配 i 个号码的彩票数
int n;

int main() {
    cin >> n;
    for (int i = 0; i < 7; i++) {
        cin >> win[i];
        is_win[win[i]] = true;
    }
    for (int i = 1; i <= n; i++) {
        int cnt = 0; // 该张彩票命中个数
        for (int j = 0; j < 7; j++) {
            int x;
            cin >> x;
            if (is_win[x]) cnt++;
        }
        ans[7 - cnt]++; // 匹配 cnt 个对应第 7-cnt 等奖
    }
    for (int i = 0; i < 7; i++) cout << ans[i] << " ";
    return 0;
}

Pythonic 写法

set 交集:

python
n = int(input())
win = set(map(int, input().split()))
ans = [0] * 7
for _ in range(n):
    hit = len(win & set(map(int, input().split())))
    if hit:
        ans[7 - hit] += 1
print(*ans)

复杂度

每张彩票只有 7 个号码,单张处理是常数时间。总时间复杂度是 O(n)O(n),空间复杂度是 O(1)O(1)

总结

这题的关键是看出“顺序无关”。用集合求交集,可以直接得到命中号码数量。