【D001】99999999海岛帝国后传:算法大会【难度:D】
——————————————————————————————————————————————————————————————————————————————————————
【题目要求】
YSF经过百般思考后,决定召开一个“煽风点火”,来召集全世界优秀的计算机人士。算法大会只有一道题,是WXJ && LJX合力编写、研究出来的算法设计精品:(以下为YSF的发言稿)
大家还记得这样一道超水,水的不能再水的题吗?(当然不是A+B问题啦)题目如上。
总体说,就是高效实现。
保证有且只有一个数符合条件。
【输入输出及要求】如图(阅读者:真懒QAQ)
【其它要求】
运行时间限制:50ms
n<=10^10,享受痛苦吧!
【试题分析】50ms达到10^10我想问的是出题者你在逗我吗?通过度娘我发现这是一个著名的主元素问题,主要思想就是通过代码选出最有可能当选的人也就是候选人。既然如此可以得到这 样的一个结论:在元素数组中,删去不同的两个元素,数组的主元素保持不变。按照这样的思路,我们可以不断缩小问题的规模,最终使问题得解:
设置变量Seed用于存储当前候选元素,初始化为数组首元素a[0];
设置变量count用于控制候选元素,初始化为1;
从第二个元素a[1]开始遍历数组,并与Seed相比较:相同,则count加1,读入下一个元素;
不同,则count减1,读入下一个元素:相当于删去两个不同元素,缩小问题规模;如果count小于0则Seed不是主元素候选,读入下一个元素,count加1。
这样一次遍历之后,得到的Seed就是主元素的候选;但因为最终得到的Seed元素有可能是序列最末位的两个元素之一,所以还需要验证。我们再次遍历数组,得到Seed出现的次数,与总数的一半比较来验证。
总的来说这个方法的效率非常高可以达到比O(n)还好。所以,完美解决。哼(ˉ(∞)ˉ)唧
【代码】
#include <iostream> using namespace std; int MajorityElement( int *a, int n) { int k, i; int elem; k = 1; elem = a[0]; for( i = 1; i <n; i++ ) { if( a[i]==elem ) k++; else { k--; if( k == 0 ) { k = 1; elem = a[i]; } } } return elem; } int main(int argc, char* argv[]) { int n; cin>>n; int a[n]; for(int i=1;i<n+1;i++) cin>>a[i]; cout<<MajorityElement(a,sizeof(a)/sizeof(a[0]))<<endl; }