【BZOJ】3576: [Hnoi2014]江南乐

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3576


 

很显然,这是一个multi-nim游戏。

 

注意:1.一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。(mex)

   2.主游戏的SG值等于所有子游戏的异或和

  

   所以区分好主游戏和后继点的区别。

     一开始多个石子堆组合起来形成了一个主游戏。

   一个石子堆可以分为多个石子堆,每一种分发构成了一个主游戏,这些主游戏的异或和构成的当前这个点(状态)的SG函数。

 

    显然有一个${m^{2}}$做法,即记忆化搜索SG函数。  

        考虑${x/i}$只有$\sqrt{n}$种取值,再考虑一下它们的奇偶性,然后分块来做。

 

70Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 100100
10 #define llg long long 
11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
12 llg n,m,bj[maxn],sg[maxn],T,F,a[maxn];
13 
14 llg dp(llg x)
15 {
16     if (bj[x]) return sg[x];
17     bj[x]=1;
18     sg[x]=0;
19     bool e[maxn];
20     memset(e,0,sizeof(e));
21     for (llg m=2;m<=x;m++)
22     {
23         llg v1=m-x%m,v2=x%m;
24         llg nsg=0;
25         if (v1&1) nsg^=dp(x/m);
26         if (v2&1) nsg^=dp(x/m+1);
27         e[nsg]=1;
28     }
29     for (llg i=0;1;i++) if (!e[i]) {sg[x]=i; return sg[x];}
30 }
31 
32 int main()
33 {
34     yyj("game");
35     cin>>T>>F;
36     for (llg i=0;i<F;i++) bj[i]=1;
37     while (T--)
38     {
39         scanf("%lld",&n);
40         llg ans=0;
41         for (llg i=1;i<=n;i++)
42         {
43             scanf("%lld",&a[i]);
44             ans^=dp(a[i]);
45         }
46         if (ans) printf("1");else printf("0");
47         if (T) printf(" ");
48     }
49     return 0;
50 }

100Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 100100
10 #define llg int
11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
12 llg n,m,bj[maxn],sg[maxn],T,F,a[maxn];
13 
14 llg dp(llg x)
15 {
16     if (bj[x]) return sg[x];
17     bj[x]=1;
18     sg[x]=0;
19     bool e[maxn];
20     memset(e,0,sizeof(e));
21     for (llg m=2,j=0;m<=x;m=j+1)
22     {
23         j=x/(x/m);
24         llg v1=m-x%m,v2=x%m,cnt=j-m+1;
25         llg nsg=0;
26         if (v1&1) nsg^=dp(x/m);
27         if (v2&1) nsg^=dp(x/m+1);
28         e[nsg]=1;
29         if (cnt>=2)
30         {
31             nsg=0;
32             if (((m+1)-x%(m+1))&1) nsg^=dp(x/(m+1));
33                    if ((x%(m+1))&1) nsg^=dp(x/(m+1)+1);
34                    e[nsg]=1;
35         }
36     }
37     for (llg i=0;1;i++) if (!e[i]) {sg[x]=i; return sg[x];}
38 }
39 
40 int main()
41 {
42     yyj("game");
43     cin>>T>>F;
44     for (llg i=0;i<F;i++) bj[i]=1;
45     while (T--)
46     {
47         scanf("%d",&n);
48         llg ans=0;
49         for (llg i=1;i<=n;i++)
50         {
51             scanf("%d",&a[i]);
52             ans^=dp(a[i]);
53         }
54         if (ans) printf("1");else printf("0");
55         if (T) printf(" ");
56     }
57     return 0;
58 }

 

posted @ 2017-02-17 22:36  №〓→龙光←  阅读(173)  评论(0编辑  收藏  举报