ACdream 1112 Alice and Bob (SG函數)

題目鏈接:
ACdream 1112

題意:
給你n  堆石子,每次要按照規則將該堆石子的個數分爲兩堆或者將該堆石子的個數減少,誰不能繼續操作了誰就輸。
規則如下:
n=ab a>1b>1  ,可以將石子分爲 ab  兩堆;或者可以減少爲 a b  。比如n=6  ,可以分爲(2,3)2,3  這三種情況,但是不能分爲(1,6),1,6  這三種情況。

題解:
對於n  個數,相當於n  個局面,只要將n  個局面異或起來就好了,所以我們就考慮一個數的時候的情況。
對每個數的素因子個數進行操作,即素數可以看做是一個1。
如果我們把x  寫成質數的冪相乘的形式就是p a 1  1 p a 2  2 p a 3  3 p a m  m  
sum=a 1 +a 2 +a 3 +.a m ; 
然後所有的情況就可以表示爲:
1sum1,(2,sum2),...(sum/2,sumsum/2)  或者(1),(2),...(n1) 
然後在計算sum  的時候我們可以這樣計算。
設一個數爲x  ,他的最小的素因子爲 y  . 則sum[x]=sum[x/y]+1 
操作的本質其實就是給一些指數降冪,也就是可以把sum  變成(0>sum1)  中的任何一個數,或者變成h 1 ,h 2   的形式,h 1 +h 2 =sum 
h 1 ,h 2   分別是兩個因子對應的sum  ,相當於sum  這個局面可以變成若干的子局面。用SG搞搞就可以了。
SG  其實就是在子局面中找一個最小的未被訪問過的數當做當前局面的值,如果你只想套結論的話這樣就夠用了。

AC代碼:

/*
* this code is made by LzyRapx
* Problem: 1112
* Verdict: Accepted
* Submission Date: 2017-07-24 17:34:31
* Time: 1368MS
* Memory: 21196KB
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5000005;
int flag[N];
int sg[100], n;
bool vis[100];

void make_prime()
{
    for(int i = 2; i < N; i++)
    {
        if(!flag[i])
        {
            for(int j = i + i; j < N; j += i) flag[j] = i;
        }
    }

}
void SG()
{
    sg[0] = 0;
    for(int i = 1; i < 100; i++)
    {
        memset(vis, false, sizeof(vis));
        for(int j = 0; j < i; j++)
        {
            vis[sg[j]] = true;
        }
        for(int j = 1; j < i; j++){
            vis[sg[j] ^ sg[i - j]] = true;
        }
        for(int j = 0;;j++)
        {
            if(!vis[j])
            {
                sg[i] = j;
                break;
            }
        }
    }
}
int solve(int x)
{
    int ret = 0;
    while(flag[x]){
        ret ++;
        x /= flag[x];
    }
    return ret + 1;
}
int main()
{
    SG();
    make_prime();
    while(~scanf("%d", &n))
    {
        int ans = 0;
        for(int i = 0, x; i < n; i++)
        { 
            scanf("%d", &x);
            int cnt = solve(x);
            ans ^= sg[cnt];
        }
        puts(ans ? "Alice" : "Bob");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章