2016年3月5日 星期六

[Codeforces 603C]Lieges of Legendre

題目連結

題目敘述

給你N堆石頭 (原題中的cow) 和數字$K$,我們來玩一個遊戲
操作1:拿掉任一堆的任一顆石頭
操作2:選個$2n$顆石頭的石頭堆,換成$K$個各有$n$顆石頭的石頭堆
不能動就輸了,請問先手勝還是後手勝?

題解

如果要看懂這個題解,請先了解組合賽局的$SG$函數和$Nim$和的性質

可以發現,每堆牛都可以視作獨立的遊戲 (想一想,為甚麼XD)
又可以發現,當$K$是偶數時,可以視作$K=0$,當$K$是奇數時,可以視作$K=1$
因為在算$Nim$和 ($XOR$) 的時候會兩兩對消

我們當然可以使用$O(a_{i})$的記憶化搜索算出每個$a_{i}$的$SG$函數值
也就是code中被註解掉的//int GetSG(const int n)
注意到
因為操作最多兩種,因此$SG$函數值只會在$[0,2]$的範圍內

再來怎麼加速呢?
找規律吧

會發現
當$K\mod 2=0$,$SG(i)=\{0,1,2,0,1,0,1,...\}$,後面皆是$01$循環
當$K\mod 2=1$,$SG(i)=\{0,1,0,1,2,0,2,0,1,...\}$,後面奇數項均為$0$,偶數項均為$1$或$2$

要判斷$K\mod 2=1$時$SG(x)$ ($x\mod 2=0$) 是$1$還是$2$,只要算算看$SG(\frac{x}{2})$是不是$1$即可
這樣複雜度為$O(\log x)$

時間複雜度:$O(\sum_{i=1}^{N}\log a_{i})$

看不懂?可參考Coding Beans的題解

code:
#include<cstdio>
#include<cassert>
#include<vector>
#include<algorithm>
using namespace std;
int N,K;
//int GetSG(const int n)
//{
//    if(n==0)return 0;
//    vector<int>sg;
//    sg.push_back(GetSG(n-1));
//    if(n%2==0)sg.push_back(K%2?GetSG(n/2):0);
//    sort(sg.begin(),sg.end());
//    int ans=0;
//    for(int i=0;i<(int)sg.size()&&sg[i]==ans;i++)ans++;
//    return ans;
//}
int GetSG(const int n)
{
    if(n==0)return 0;
    if(K%2==0)
    {
        if(n==1)return 1;
        if(n==2)return 2;
        if(n==3)return 0;
        if(n==4)return 1;
        if(n==5)return 0;
        if(n==6)return 1;
        return n&1?0:1;
    }
    else
    {
        if(n==1)return 1;
        if(n==2)return 0;
        if(n==3)return 1;
        if(n==4)return 2;
        if(n==5)return 0;
        if(n==6)return 2;
        if(n==7)return 0;
        if(n==8)return 1;
        if(n%2)return 0;
        else return GetSG(n/2)==1?2:1;
    }
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&N,&K)==2)
    {
//        for(int i=0;i<100;i++)printf("%d ",GetSG(i));printf("%d\n",GetSG(100));
        int ans=0;
        for(int i=0,v;i<N;i++)scanf("%d",&v),ans^=GetSG(v);
        printf("%s\n",ans==0?"Nicky":"Kevin");
    }
    return 0;
}

沒有留言:

張貼留言

歡迎留言或問問題~
若您的留言中包含程式碼,請參考這篇
如果留言不見了請別慌,那是因為被google誤判成垃圾留言,小莫會盡快將其手動還原

注意:只有此網誌的成員可以留言。