首页 > 其他分享 >【noip赛前20天冲刺集训 day4】正在出模拟赛

【noip赛前20天冲刺集训 day4】正在出模拟赛

时间:2023-10-12 17:22:24浏览次数:95  
标签:参加 比赛 noip 账号 day4 用户 leq 使用 20

题目描述

想象学竞赛网站 CodeFancy 举办了 \(m\) 场比赛。你在 CodeFancy 上关注了 \(n\) 个账号,编号为 \(1\) 到 \(n\)。你知道这 \(n\) 个账号分别参加了 \(m\) 场比赛中的哪些。但是你发现可能存在一个人使用多个账号的情况,你想知道这 \(n\) 个账号的使用者最少共有多少人。

具体地,账号和使用者的关系由两条规则限定:

  1. 一个人在一场比赛中至多使用一个账号。
  2. 一个账号的使用者只有恰好一个人。

输入格式

第一行两个正整数 \(n\) 和 \(m\)。

接下来 \(m\) 行,每行先输入一个正整数 \(k\),表示参加这场比赛的账号数量;接下来输入 \(k\) 个正整数,表示参加这场比赛的账号编号。

输出格式

一行一个非负整数,表示最少的人数。

样例

输入样例

5 3
2 1 2
3 2 3 4
4 4 5 1 2

输出样例

4

样例解释

一种合法的方案是,四个人使用的账号集合分别为:{1,3},{2},{4},{5}。

可以证明,不存在人数更少的合法方案。

数据范围

本题使用捆绑测试,子任务信息如下:

子任务编号 \(m\) 分值
1 1 10
2 2 20
3 3 30
4 4 40

对于 \(100\%\) 的数据,保证 \(1 \leq n \leq 10^5\),\(1 \leq m \leq 4\),\(1 \leq k \leq n\)。

  • 解题思路:

    题目背景

    在一个编程竞赛平台上,有许多用户参加了多场比赛。每个用户可能拥有一个或多个账号,但规则是一个用户在同一场比赛中只能使用一个账号。给定每场比赛中参与的账号,目标是找出最少需要多少个独立的用户。

    • 解题思路

      步骤1: 编码参赛情况

      首先,我们将每个账号的参赛情况编码为一个0到16之间的整数。这是通过将每场比赛视为一个位,如果账号参加了该比赛,则该位为1;否则为0。这样,每个账号都可以用一个整数表示其参赛情况。

      步骤2: 计数相同参赛情况的账号

      • 接下来,我们计算具有相同参赛情况的账号数量。这是通过使用一个数组 a[] 完成的,其中 a[i] 存储具有相同编码 i 的账号数量。

        步骤3: 贪心凑合

      • 然后,我们使用贪心策略尝试用最少的用户数覆盖所有账号。我们首先处理那些参加了最多比赛的账号,因为它们可以覆盖更多的比赛。具体操作如下:

      • 处理全覆盖账号: 如果有账号参加了所有比赛(即编码为 15),我们首先选择这些账号,因为它们单独就覆盖了所有比赛。

      • 配对互补集合: 对于剩下的账号,我们尝试找到互补的账号集合来覆盖所有比赛。例如,如果一个账号的编码是 12,我们会寻找编码为 3 的账号,因为这两个账号合起来可以覆盖所有比赛。

      • 处理剩余账号: 对于不能与其他账号形成全覆盖配对的账号,我们尝试将它们分配给新的用户,同时确保这些新用户尽可能多地参加比赛。

      步骤4: 输出结果

      • 最后,我们得到了覆盖所有账号所需的最少用户数。 ### 根据输入:
        5 3 2 1 2
        3 2 3 4
        4 4 5 1 2
      • 账号的参赛情况如下:

      - 	账号 1: 参加了比赛 1 和 3。
      - 	账号 2: 参加了比赛 1、2 和 3(所有比赛)。
      - 	账号 3: 只参加了比赛 2。
      - 	账号 4: 参加了比赛 2 和 3。
      - 	账号 5: 只参加了比赛 3。
      
      • 按照你的策略,我们首先选择参加比赛最多的账号。在这里,账号 2 参加了所有比赛,所以我们首先选择它。由于账号 2 已经参加了所有的比赛,我们需要考虑其它的账号。在这种情况下,由于账号 2
        已经覆盖了所有比赛,我们不需要选择其它账号,因为它们至少参加了账号 2
        已经参加的比赛。然而,由于规则规定一个人在一场比赛中只能使用一个账号,所以参加同一场比赛的其它账号不能由账号 2 的用户使用。
        因此,我们需要为参加了同一场比赛的其它账号分配不同的用户。在这个例子中:

      • 账号 1 可以由一个新用户使用,因为它与账号 2 参加了相同的比赛。

      • 账号 3 也需要一个新用户,因为它与账号 2 和账号 4 参加了比赛 2。

      • 账号 4 可以由账号 3 的用户使用,或者需要一个新用户(如果账号 3 的用户不使用它)。

      • 账号 5 需要一个新用户,因为它与账号 2 和账号 4 参加了比赛 3。
        综上所述,最少需要的用户数是 4:一个用户使用账号 2,三个新用户分别使用账号 1、3 和 5。这样,每个用户都遵守了规则,而且账号 2 的用户参加了最多的比赛。
        这个策略确保了我们以最有效的方式使用了每个账号,同时遵守了比赛的规则。

AC代码

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

// 定义一些宏来简化代码
#define rep(i, s, e) for (int i = s; i <= e; ++i)
#define drep(i, s, e) for (int i = s; i >= e; --i)

const int N = 1e5 + 10;

// 定义函数读取输入数据
int read() {
    int x = 0, f = 1;
    char c = getchar();
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
    for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - 48;
    return x * f;
}

// 定义函数计算一个数的二进制表示中1的个数
int pc(int s) {
    return __builtin_popcount(s);
}

int n, k, ans, a[N], cnt[16];

int main() {
    // 读取账号数和比赛数
    n = read(), k = read(), ans = n;

    // 读取每场比赛的参与账号,并更新它们的参赛情况
    rep(i, 0, k - 1) {
        for (int c = read(), p; c; --c) {
            p = read();
            a[p] |= 1 << i;  // 使用位运算记录账号 p 参加了哪些比赛
        }
    }

    // 计算每种参赛情况的账号数
    rep(i, 1, n) ++cnt[a[i]];

    ans = 0; // 重置答案为0,准备通过计算得出

    // 定义一个 lambda 函数来更新答案
    auto upd = [&](int s) {
        // 找到参赛情况互补的账号集合,并更新答案
        int t = min(cnt[s], cnt[15 ^ s]);
        ans += t;
        cnt[s] -= t;
        cnt[15 ^ s] -= t;
    };

    // 对于参加了多于一场比赛的账号,尝试找到互补集合
    rep(s, 0, 15) if (pc(s) > 1) upd(s);

    // 对于参加了多于两场比赛的账号,直接将它们计入答案
    rep(s, 0, 15) if (pc(s) > 2) ans += cnt[s];

    // 对于只参加了一场或两场比赛的账号,尝试配对它们
    rep(i, 0, 3) rep(j, i + 1, 3) {
        int t = min(cnt[15 ^ (1 << i) ^ (1 << j)], min(cnt[1 << i], cnt[1 << j]));
        ans += t;
        cnt[15 ^ (1 << i) ^ (1 << j)] -= t;
        cnt[1 << i] -= t;
        cnt[1 << j] -= t;
    }

    // 对于剩下的账号,尝试将它们分配给新的用户
    rep(k, 0, 3) rep(i, 0, 3) rep(j, i + 1, 3) {
        if (k == i || k == j || !cnt[(1 << i) | (1 << j)]) continue;
        int t = min(cnt[(1 << i) | (1 << j)], cnt[1 << k]);
        ans += t;
        cnt[(1 << i) | (1 << j)] -= t;
        cnt[1 << k] -= t;
    }

    // 最后,处理只参加了两场比赛的账号,并找出只参加了一场比赛的账号中数量最多的
    rep(s, 0, 15) if (pc(s) == 2) ans += cnt[s];
    ans += max(max(cnt[1], cnt[2]), max(cnt[4], cnt[8]));

    // 输出答案,如果答案小于1(即没有账号参加比赛),则输出1
    printf("%d\n", max(ans, 1));

    return 0;
}



标签:参加,比赛,noip,账号,day4,用户,leq,使用,20
From: https://www.cnblogs.com/Serein-KarBlog/p/17760015.html

相关文章

  • LeetCode Day02 977&209&59
    第一题是[977. 有序数组的平方]这题解题思路依旧可以用双指针,指针分别指向数组的头尾两端,然后对两端求乘积比较大小,把乘积值更大的存储到数组尾端,然后指针更新位置,代码如下。publicint[]sortedSquares(int[]nums){//res用于存储平方和结果int[]res=ne......
  • 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror
    有五种种类的垃圾,数量分别为\(a_1,a_2,a_3,a_4,a_5\)。第一种为纸质垃圾第二种为塑料垃圾第三种双非垃圾第四种基本纸质垃圾第五种基本塑料垃圾有三种垃圾桶,容量分别为\(c_1,c_2,c_3\)。第一种垃圾桶可以放入:纸质垃圾和基本纸质垃圾第二种垃圾桶可以放入:塑料......
  • 2023.10.9NOIPSIM1总结
    ##T1区分度先手算一下找下规律,发现数列呈现$1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8......$的规律。数据范围到$1e13$,考虑数论分块,每块的块长由前一块块长递推得到。在块内累$\Omicron$(1)累计答案,跳块时间复杂度$\Omicron$($\sqrtn$),总复杂度$\Omicron(t\sqr......
  • 测试4 20211102尹子扬静态库的测试
    1.首先,编译你的模块源代码成为目标文件(.o文件)。例如,如果有一个模块名为mymath.c,你可以使用以下命令来生成目标文件:点击查看代码gcc-cmymath.c-omymath.o请确保你以适当的方式编译所有的模块源代码文件。2.将所有目标文件打包成一个静态库文件。你可以使用ar命令来......
  • 【2023年10月12日】stf61-MySQL数据库
     stf61-MySQL数据库前言1)为什么学?● 常见的笔试题● 有利于更好的开展测试工作2)学什么?理论:基本的术语和概念实操:数据库操作、表操作、数据操作、其他常见数据库功能3)怎么学?多在实训环境里练习,在练习中掌握 理论 数据库系统: 表:8条记录/行,6个字段/列 ......
  • getMonth():获取当前月(注意:返回数值为0~11,需要自己+1来显示),0代表一月份,如果要显示2位
    getMonth():获取当前月(注意:返回数值为0~11,需要自己+1来显示),0代表一月份,JavaScriptDate对象 日期选择控件的主要功能是向用户提供包含年、月、日的日期数据并并允许用户对其修改。如果要捕获用户修改日期选择控件的数据事件响应,需要为DataPicker添加一个OnDateChangedListene......
  • 2023/10/12
    2023/10/12今日词汇intensity强度render(vt.)使变得;(v.)提供;翻译;表达熟词僻意volume(n.)音量今日词组graspmusicitself领会音乐本身byallaccounts总而言之letalone更不用说......
  • 2023柏鹭杯pwn wp
    PWN博客eval漏洞点对数组模拟栈的那个栈顶没做下溢校验,先输入符号可以构成溢出点+200/2+(target_offset-100)这样输入即可将栈顶迁移到任意位置难点需要逆向整个模拟栈的结构可以配合动态调试得出模拟栈结构addr+00addr+1符号位addr+20addr+3栈顶偏移addr+4......
  • 智能充电未来之路:ISO 15118-20的关键角色
    随着越来越多的电动汽车进入到大众的视野,对电动汽车的充电技术要求也变得越来越高,在ISO15118协议中表明,电动汽车可以使用智能充电的方式进行充电,可以大大提高充电效率。  ISO15118  ISO15118是一项国际标准,定义了电动汽车和充电桩之间的通信协议,这项标准包括了车辆与......
  • GitHub发布2021年度报告:中国开发者数量全球第2 ,最受欢迎的语言是
    临近年底,各大平台年终报告频频发布。作为程序员,应该关注些什么呢?近日,全球最大开发者社区GitHub重磅发布了《2021年度Octoverse报告》,本报告首次结合了来自GitHub上,超过400万个代码库的数据,共有超过12000多名开发者参与问卷调查。在即将过去的2021年,开发者社区发生了哪些有趣......