1. 程式人生 > >uva1482:Playing With Stones (SG函式)

uva1482:Playing With Stones (SG函式)

題意:有N堆石子,每次可以取一堆的不超過半數的石子,沒有可取的為輸。

思路:假設只有一堆,手推出來,數量x可以表示為2^p-1形式的必輸。 但是沒什麼用,因為最後要的不是0和1,而是SG函式;所以必輸的為0,那麼其他的呢?

我們可以發現SG=0的位置是1,3,7,15,31....

                     SG=1,            2,5,11,23....

可以推出來,也可以打表。

(水題,這題可以放這裡以後講課用。

    sg[1]=0;
    for(int i=2;i<=30;i++){
        memset(vis,0,sizeof(vis));
        for(int j=1;j<=i/2;j++) vis[sg[i-j]]=1;
        for(int j=0;;j++){
            if(!vis[j]) {sg[i]=j; break;}
        }
    }
    for(int i=1;i<=30;i++) cout<<i<<"
"<<sg[i]<<endl;

完整程式碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll SG(ll x){
    if(x&1LL) return SG(x/2);
    return x/2;
}
int main()
{
    int T,N,ans; ll x,q;
    scanf("%d",&T);
    while(T--){
        ans=0; scanf("%d",&N);
        
for(int i=1;i<=N;i++){ scanf("%lld",&x); ans^=SG(x); } if(ans) puts("YES"); else puts("NO"); } return 0; }