Nim or not Nim? HDU

题意:给定n堆石子,两人轮流操作,每次选一堆石子,取任意石子或则将石子分成两个更小的堆(非0),取得最后一个石子的为胜。

题解:比较裸的SG定理,用sg定理打表,得到表1,2,4,3,5,6,8,7,9,10,12,11...可以发现当x%4==0时sg[x]=x-1;当x%4==3时sg[x]=x+1;其余sg[x]=x。然后异或下就出来结果了。

打表:

#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
const int maxn=1e4+10;  
int sg[maxn],vis[maxn];  
void solve()  
{  
    int i,j,k;  
    sg[0]=0,sg[1]=1;  
    for(i=2;i<=1000;i++)  
    {  
        memset(vis,0,sizeof(vis));  
        for(j=1;j<i;j++)  
        vis[sg[j]^sg[i-j]]=1;  //拆分  
        for(j=0;j<i;j++)  
        vis[sg[j]]=1;         //取石子  
        for(j=0;;j++)  
        if(!vis[j])break;  
        sg[i]=j;  
    }  
    for(i=1;i<=20;i++)  
    cout<<sg[i]<<endl;  
}  
int main()  
{  
    solve();  
}
View Code

AC:

#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
const int maxn=1e6+10;  
int find(int x)  
{  
    if(x%4==0)return x-1;  
    else if(x%4==3)return x+1;  
    return x;  
}  
int main()  
{  
    int T;  
    scanf("%d",&T);  
    while(T--)  
    {  
        int a,n,i,j,ans=0;  
        scanf("%d",&n);  
        for(i=0;i<n;i++)  
        {  
            scanf("%d",&a);  
            ans=ans^find(a);  
        }  
        if(ans==0)printf("Bob
");  
        else printf("Alice
");  
    }  
    return 0;  
}
View Code
原文地址:https://www.cnblogs.com/astonc/p/9990945.html