UVALive - 5059

组合游戏UVALive - 5059
输入n和n个数,n堆石子。每次不能拿超过该堆石子的一半;
二人轮流去,最后没的取的为输。
求SG值;sg(x)=mex(sg(y)|y为x的后继)
这里sg(x)=mex(sg(x-1),sg(x-2)..sg(ceil(x/2)));
sg(1)=0;sg(2)=1;sg(3)=0;sg(4)=2;sg(5)=1
当x为偶数时,mex()中必定有x/2个数,且[0,x/2-1];所以sg(x)=x/2;
当x为奇数时,mex()中有(x-1)/2个数,x-1为偶数,sg(x-1)里也有(x-1)/2个数;
sg(x-1)=mex(sg(x-2),sg(x-3)..sg(x-(x-1)/2-1));
sg(x)=mex(sg(x-1),sg(x-2)..sg(x-(x-1)/2));里面的数都不会重复的。
sg(x-1)必定是最大的。所以sg(x)=sg(x-(x-1)/2-1)),即sg(x)=sg((x-1)/2);
然后像nim游戏异或一下就可以得出结果。。

这题坑爹的是必须得cin,cout输入输出才能对,坑爹的OJ啊。。

提交无数次,最后顶不顺了,看别人AC代码,还是不知道怎么错,然后照着它们来改,最后发现要C++输入输出。。

我是见识太少,还是太坑爹啊。。我都快被它气晕了。。

AC代码:

 1 #include<iostream>
 2 #define ll long long
 3 using namespace std;
 4 ll sg(ll x)
 5 {
 6     if (x&1) return sg(x>>1);
 7     return x>>1;
 8 }
 9 int main ()
10 {
11     int t,n;
12     cin>>t;
13     while (--t>=0)
14     {
15         cin>>n;
16         ll num,ans=0;
17         while (--n>=0)
18         {
19             cin>>num;
20             ans^=sg(num);
21         }
22         if (ans) cout<<"YES"<<endl;
23         else cout<<"NO"<<endl;
24     }
25     return 0;
26 }

 

posted @ 2012-11-23 00:26  _hikaru__  阅读(231)  评论(0编辑  收藏  举报