主元素问题与摩尔投票法、格雷码

一堆小玩意,放到一起。

题意:给定一个n个元素数列,保证有一个数a的出现次数超过n2,求这个数。

数据范围n<=3000000,ai2147483647,时限0.5s,空间2M。

也就是说你就只开几个变量就行了。(虽然考试的时候有人拿hash玄学乱搞过了)

首先这个时间卡掉了排序,空间和数据范围卡掉了桶的做法。我们考虑利用“数a的出现次数超过n2”这个特性。

我们发现(反正我没发现我太弱了55555)如果两两删去两个不同的元素,最后剩下的一定是元素a。证明考虑最坏的情况,所有其他元素一起来删掉a,那么由于a的个数超过一半,一定可以删掉其他所有的元素而自身有保留元素。

于是我们就得到了一种O(n)模拟的方法,而且只需要四个int变量:n,输入的x,计数器cnt,ans。具体地,我们每次输入一个数的时候,进行如下操作:

  1. 如果cnt=0,则用x更新ans,将cnt设为1
  2. 如果xans,则将当前计数器cnt1。(也就是用不同的元素互相消去)
  3. 反之cnt+1。(也就是统计相同的元素个数)

依题意模拟即可。

scanf("%d",&n);
while(n--){
	int x;scanf("%d",&x);
	if(ans!=x){
		if(--cnt<=0)ans=x,cnt=1;
	}
	else cnt++;
}

反正我觉得不会考,但是考了就考了吧。


格雷码是一个二进制数系,其中两个相邻数的二进制位只有一位不同。

给出手动构造方法:

  1. 翻转最低位得到下一个格雷码。
  2. 翻转最右边的1的左边一位得到下一个格雷码。

交替操作1,2共2k1次可得到k位的格雷码序列。举个例子,3位格雷码序列为:

000,001,011,010,110,111,101,100

注意我们说的格雷码下标是从0开始的,即G(0)=000,G(4)=110

然后是计算法:第n位格雷码为:

G(n)=nn2

int g(int n){
	return n^(n>>1);
}

然后是它的逆变换。n的二进制第i位与其格雷码g的二进制第i位的关系(最高位为k):

nki=j=0igkj

int getn(int g){
	int n=0;
	for(;g;g>>=1)n^=g;
	return n;
}
posted @   gtm1514  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示