1. 程式人生 > >【題解】Luogu P2397 yyy loves Maths VI (mode)

【題解】Luogu P2397 yyy loves Maths VI (mode)

problem

很有意思的一道題

Solution

初看此題毫無頭緒,2.2mb太喪心病狂了

再看題目,注意到重要性質:眾數個數大於一半

看完題解之後想到使用一個方法:摩爾投票法

摩爾投票法是啥玩意?

考慮一段序列,其中眾數的個數超過一半

每一輪投票,從序列中選出兩個不同的數,丟棄

無法再進行投票後,最終一定剩下大於等於一個全部相同的數,即眾數

會不會有剩兩種或以上不同的數?

不會。根據定義,此時我們還可以再進行一次投票

很好,可是要怎麼用到題目上面?

十分極限的空間限制要求我們的演算法空間複雜度為\(O(1)\)

以下引用自PauGasol的高票題解

我們來yy一個小房子,每當有數進來的時候,如果房子是空的,那麼將這個房子貼上自己的標籤。
如果房子裡已經有和自己相同數字了,那麼進去和它一起♂住。
如果房子裡有和自己不同的數字,帶一個走出♂房♂子。
最後房子裡還剩下的數一定就是眾數了。

生動形象,驚世駭俗,一針見血(bushi

實際上這就是在運用摩爾投票法了,每次走出去的兩個數字是不同的,最終剩下的數即是眾數

Code

#include <cstdio>
using namespace std;

int n;
int cur,cnt;

int main()
{
    scanf("%d",&n);
    int t;
    for(register int i=1;i<=n;++i)
    {
        scanf("%d",&t);
        if(!cnt)
            cur=t;
        if(cur==t)
            ++cnt;
        else
            --cnt;
    }
    printf("%d",cur);
} 

Solution II

在我把這道題直球安利給機房P神@srydsf123之後,P神花了三秒鐘稍作思考,說我還是\(naive\),提出了一個跟位有點關係的解決方案

陣列\(cnt[i][j]\)表示第\(i\)位上為\(j\)的數字的個數

可以發現眾數各位上的各個數在所在位上的個數一定大於\(n/2\),且在所有數中個數最多

為什麼最多?

顯然其他的數字的個數一定小於\(n/2\)

Code

懶得打了