彩票摇奖系统:集合运算与模式匹配的C++实现(洛谷P2550)

题目思路解析

这道彩票摇奖题目要求我们根据中奖号码判断多张彩票的中奖等级。核心在于高效计算彩票号码与中奖号码的交集大小,并根据交集大小确定中奖等级。

核心思考路径

  1. 数据读取:读取中奖号码和所有彩票号码
  2. 交集计算:对每张彩票计算与中奖号码的匹配个数
  3. 等级判定:根据匹配个数确定中奖等级
  4. 结果统计:统计各等级的中奖张数

关键考核知识点

1. 集合运算应用(⭐⭐⭐⭐⭐)

  • 交集计算:快速判断号码是否存在
  • 哈希集合:使用unordered_set实现O(1)查找
  • 批量匹配:同时处理多个号码的匹配

2. 计数与统计(⭐⭐⭐)

  • 等级映射:匹配个数到中奖等级的转换
  • 结果累计:统计各等级的中奖数量
  • 输出格式化:按要求格式输出结果

3. 输入输出处理(⭐⭐)

  • 多行数据读取:处理不定数量的彩票数据
  • 数据验证:确保号码在合法范围内
  • 输出顺序:按特等奖到六等奖的顺序输出

C++完整实现

#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 读取中奖号码
    unordered_set<int> winning_numbers;
    for (int i = 0; i < 7; ++i) {
        int num;
        cin >> num;
        winning_numbers.insert(num);
    }
    
    // 初始化中奖等级计数器
    vector<int> prize_count(7, 0); // 索引0:特等奖, 1:一等奖, ..., 6:六等奖
    
    // 处理每张彩票
    for (int i = 0; i < n; ++i) {
        int match_count = 0;
        
        // 读取彩票号码并计算匹配个数
        for (int j = 0; j < 7; ++j) {
            int num;
            cin >> num;
            if (winning_numbers.find(num) != winning_numbers.end()) {
                match_count++;
            }
        }
        
        // 根据匹配个数确定中奖等级
        if (match_count >= 1 && match_count <= 7) {
            prize_count[7 - match_count]++;
        }
    }
    
    // 输出结果
    for (int i = 0; i < 7; ++i) {
        cout << prize_count[i];
        if (i < 6) cout << " "; // 可选:添加空格分隔
    }
    cout << endl;
    
    return 0;
}

代码解析与优化

1. 数据结构选择优化

// 使用unordered_set提高查找效率
unordered_set<int> winning_numbers;
// 替代方案:使用数组标记(当号码范围较小时)
bool number_exists[34] = {false};

2. 匹配计数优化

// 使用位运算或预计算优化
// 如果号码范围小,可以用位图表示

3. 复杂度分析

操作时间复杂度空间复杂度说明
读取中奖号码O(7)O(7)常数时间
处理单张彩票O(7)O(1)每张彩票7次查找
总体复杂度O(7n)O(7)线性复杂度

测试用例分析

测试案例输入预期输出验证要点
样例12
23 31 11 14 19 17 18
12 8 9 23 1 16 7
11 7 10 21 2 31
0 0 0 0 0 1 1基本功能
边界11
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 0 0 0 0 0 0特等奖情况
边界21
1 2 3 4 5 6 7
8 9 10 11 12 13 14
0 0 0 0 0 0 0未中奖情况
特殊13
1 2 3 4 5 6 7
1 2 3 8 9 10 11
1 8 9 10 11 12 13
8 9 10 11 12 13 14
0 0 1 0 1 0 1多等级中奖

常见错误与修正

错误1:等级映射错误

// 错误:直接使用匹配个数作为索引
prize_count[match_count]++; // 特等奖应该是7,但索引7越界

修正

prize_count[7 - match_count]++; // 特等奖对应索引0

错误2:集合查找错误

// 错误:错误的使用find方法
if (winning_numbers.find(num)) // 应该检查是否等于end()

修正

if (winning_numbers.find(num) != winning_numbers.end())

错误3:输出格式错误

// 错误:输出顺序错误
for (int i = 0; i < 7; i++) {
    cout << prize_count[i] << endl; // 应该在一行输出
}

修正

for (int i = 0; i < 7; i++) {
    cout << prize_count[i];
}
cout << endl;

竞赛技巧总结

  1. 数据结构选择:根据数据特性选择合适的数据结构
  2. 算法优化:利用哈希集合实现快速查找
  3. 边界测试:测试全中、全不中等边界情况
  4. 代码简洁:保持逻辑清晰,避免复杂嵌套

拓展思考

1. 性能优化进阶

// 使用bitset优化空间(当号码范围固定时)
bitset<34> winning_numbers; // 33个号码+1个索引偏移

2. 功能扩展

// 支持多组中奖号码
vector<unordered_set<int>> multi_winning_numbers;
// 计算最佳中奖等级

3. 错误处理增强

// 添加输入验证
bool validateNumber(int num) {
    return num >= 1 && num <= 33;
}

"彩票摇奖问题展示了如何将现实世界的规则转化为高效的算法实现,是集合运算在实际应用中的典型例子。"

实际应用价值

  • 彩票系统开发
  • 抽奖活动程序设计
  • 模式匹配算法实践

通过这道题目,我们不仅学会了算法实现技巧,更理解了如何将业务规则转化为可执行的代码逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨小码不BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值