题目
题目 2315: [传智杯]众数出现的次数
时间限制: 5Sec 内存限制: 512MB 提交: 318 解决: 120
题目描述
传智专修学员的课堂上,为了活跃气氛,并巩固位运算的知识,同学们玩起了一个游戏。
班级里有 n(n<=10^6) 名同学,每位同学都获得了两张卡,红卡或者黑卡。每张卡上都有一个不超过 10^9 的非负整数。第 i 位同学手里红卡数字是 ai ,黑卡数字是 bi。
现在需要每位同学出牌。每位同学可以直接将红卡上的数字打出,或者将自己的红卡上的数字和自己黑卡数字进行按位异或操作后的结果打出。最后老师会收集所有同学打出的数字。
这些数字中出现次数最多的数字是众数。在所有同学合作的最优策略下,我们希望众数对应数字出现的次数尽可能多。请问出现次数最多的数字是多少呢?
输入
第一行,一个正整数 n。
接下来 n 行,其中第 i 行时非负整数 ai,bi 代表第 i 名同学手上红卡和黑卡的数字。
输出
一个整数,表示答案。如果有多个解,请输出最小的那个。
样例输入
4
21 9
28 9
28 3
17 4
样例输出
21
提示
样例解释:
众数出现次数最多是 3 次,有如下两种方法:
1 号同学直接出红卡,2 号同学出红黑异或,3 号同学随便出,4 号同学出红黑异或。这样 1,2,4 号同学都可以打出 21。
1 号同学出红黑异或,2 号同学直接出红卡,3 号同学直接出红卡, 4 号同学随便出。这样 1,2,3号同学都可以打出 28。
所以 21 和 28 都是出现次数最多的众数,因为最多可以出现 3 次,不存在出现 4 次的方案。但是由于要求如果有多解输出小的,请输出 21。
分析
这个题在当时比赛时没有做出来,觉得很难。
假设有n(n<=1e6)个同学,每个同学有可能出红卡,有可能出红与黑异或后的卡,虽然两种方式可能出现相等,如果不考虑相等,那最后的出牌将是2的n次方种组合,如果我去找众数,那我怎么记录呢,每个同学的数字范围是1e9,太大了吧!
看题解后的分析
1.对于2的n次方种组合,这个不用管,我把所有可能出现的数记录一下,6出现的次数最多,那么6就是众数,算这个的时候要注意一下,如果红卡和红与黑异或后的结果一样,那得算一次。
2.我们需要一个数组,这个数组要存每个数出现的次数,但是这个数的最大是1e9,数组开不了这么大,解决办法
(1)映射
(2)也是映射,直接c++中的map,map<int ,int>.
代码:
/*
* Copyright(c)
* All rights reserved.
* Author : Michael
* Date : 2020-04-26-14.32.54
*/
#include<iostream>
#include<algorithm>//快排sort()
#include<cstdio>//能不用cin就不用
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<set>
#define ll long long
using namespace std;
int main(){
int n;
int a,b;
cin>>n;
map<int ,int >mp;
mp.clear();
for(int i=1;i<=n;i++){
scanf("%d%d",&a,&b);
if(a!=(a^b)){
mp[a]++;//其实就是a出现的次数+1
mp[a^b]++;
}
else{
mp[a]++;
}
}
int _max=-1,pos;
int x,y;
for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++){//这一句是迭代器遍历
x=it->second;
y=it->first;
if(x>_max) {pos=y;
_max=x;}
else if(x==_max){
pos=min(pos,y);//如果这时两个众数,要取最小的那个,这是题意
}
}
cout<<pos<<endl;
return 0;
}