P6365 [传智杯 #2 初赛] 众数出现的次数

122 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

[传智杯 #2 初赛] 众数出现的次数

题目描述

传智专修学员的课堂上,为了活跃气氛,并巩固位运算的知识,同学们玩起了一个游戏。

班级里有 n(n106)n(n\le10^6) 名同学,每位同学都获得了两张卡,红卡或者黑卡。每张卡上都有一个不超过 10910^9 的非负整数。第 ii 位同学手里红卡数字是 aia_i ,黑卡数字是 bib_i

现在需要每位同学出牌。每位同学可以直接将红卡上的数字打出,或者将自己的红卡上的数字和自己黑卡数字进行按位异或操作后的结果打出。最后老师会收集所有同学打出的数字。

这些数字中出现次数最多的数字是众数。在所有同学合作的最优策略下,我们希望众数对应数字出现的次数尽可能多。请问出现次数最多的数字是多少呢?

输入格式

第一行,一个正整数 nn

接下来 nn 行,其中第 ii 行时非负整数 ai,bia_i,b_i 代表第 ii 名同学手上红卡和黑卡的数字。

输出格式

一个整数,表示答案。如果有多个解,请输出最小的那个。

样例 #1

样例输入 #1

4
21 9
28 9
28 3
17 4

样例输出 #1

21

提示

样例解释:

众数出现次数最多是 33 次,有如下两种方法:

  • 11 号同学直接出红卡,22 号同学出红黑异或,33 号同学随便出,44 号同学出红黑异或。这样 1,2,41,2,4 号同学都可以打出 2121
  • 11 号同学出红黑异或,22 号同学直接出红卡,33 号同学直接出红卡,44 号同学随便出。这样 1,2,31,2,3 号同学都可以打出 2828

所以 21212828 都是出现次数最多的众数,因为最多可以出现 33 次,不存在出现 44 次的方案。但是由于要求如果有多解输出小的,请输出 2121

思路分析

刚开始看到这题我愣住了,先是看到了有十的六次方的人数,每个人还有两种机会,这怎么做?铁定炸啊!但是仔细的分析你会发现,不对劲,太不对经了,这只是初赛的第三题而已,怎么会这么难?
于是我想到了map的映射,我们只需要记录一下卡牌数值可能会出现的次数就行了!

  • 首先创建一个map<int,int>mp的映射
  • 接着将数据存入
    • 对于红牌需要直接存入
    • 但是对于红牌与黑牌的位异或,要前置判断一下是否会出现值与红牌相等的情况,若相等则不能存储
  • 然后线性遍历,找到最大的,因为有map排序,所以即使在后面有等值的,也会优先考虑小的

代码展示

//异味或^
#include<iostream>
#include<map>
using namespace std;

map<int, int>mp;

int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int a, b;
		cin >> a >> b;
		mp[a]++;
		if (a != (a ^ b))mp[a ^ b]++;
	}
	int count = 0, res = 0;
	for (map<int, int>::iterator it = mp.begin(); it != mp.end(); it++)
		if (it->second > count)count = it->second, res = it->first;
	cout << res;
	return 0;
}

PS:差点被第三题吓到了~