zoukankan      html  css  js  c++  java
  • [洛谷P2397]yyy loves Maths VI (mode)

    题目传送门

    这道题题面十分简单,貌似不难,但空间一限制就比较麻烦了。

    其实了解了一些比较重要的东西就很简单了。

    先不切入重点。

    方法一

    如果一个数过半,如果将这个数转成二进制的形式,则该数对应的每位上的数(不是$0$就是$1$)一定过半(指其他数的对应数位$0$或$1$的统计)。

    举个例子:有一串数列${ 2,2,3,2,1,2}$。把每个数换成二进制即为:

    $10$、$10$、$11$、$10$、$01$、$10$。

    发现第一位$1$出现比$0$次数多,第二位$0$比$1$多。所以过半的数的二进制为$10$、即为$2$。

    这个方法比较冷门,好像并无卵用常数较大但能过(过了读入毒瘤即可)。

    方法二

    步入正解:摩尔投票法

    步骤:

    (1)两个变量:$now\_num$、$count$;

    (2)读入数$val$;

    (3)如果$val$不等于$now\_num$,让$count$自减。如果本来$count$为$0$,标记$now\_num$为$val$并让$count$为1;

    (4)否则$count$自加;

    (5)重复步骤(2)。

    正确性:会发现对于每一个$val$都会抵消掉一个不等于它的$val$,而所求的数过半,所以这个数会抵消掉其他所有数且还有过剩的。

    注意这个性质具有可加性。也就是可以用线段树等数据结构维护。

    假如求过了三分之一的数呢?有摩尔投票法的扩展。

    然而我太弱了不知道其实就是搞两个$now\_num$和$count$弄一下。

    最后这道题要注意读入快读啥的都挂了,必须要$scanf$才不被卡原理玄学。

     1 int n, v, x, cnt = 0;
     2 
     3 int main() {
     4     scanf("%d", &n);
     5     rep(i, 1, n) {
     6         scanf("%d", &x);
     7         if (cnt == 0) v = x;
     8         cnt += v == x ? 1 : -1;        
     9     }
    10     printf("%d", v);
    11     return 0;
    12 }
  • 相关阅读:
    小说下载器【追书接口】
    C#调用大漠插件,发送QQ和微信消息
    C# 终本案件、综合执行人、裁判文书爬虫
    追书神器API
    一个CookieContainer的拓展类
    利用BlockingCollection实现生产者和消费者队列,实现写文本
    EF SQLite的Like语句,生成为CHARINDEX的解决办法
    ClientKey实现登录QQ空间,并设置背景音乐
    DataTable转换为Model实体对象
    开通博客第一天!
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10367142.html
Copyright © 2011-2022 走看看