HDU 3595 GG and MM
EVERY SG:
在验算的过程中,我们可以发现如果X,Y,X>Y而且X / Y==1,则每次从X中取走Y,这步的选择是固定的,但是当X / Y>=2的情况就不一样了,可以控制步数。
在这个游戏中,由于是Every_SG,我们考虑的是步数,
首先,利用辗转相除法计算最原始的步奏
其次,看谁如果拥有第一个X/Y>=2,便具有优先权,可以控制,将 所有的X/Y>=2控制在自己手中,到了最后一个让自己获胜。以上的策略全部由奇偶来决定,如果在某一步操作的时候,第一个和第二个满足X / Y >=2的点,之间原始步奏的奇偶性,如果是相同的奇偶性那么就不需要改变步数,如果是不同的奇偶性,那么就要将步数加一以实现最优策略, 以此得到最大的步数,判断奇偶。#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------------------------------
const int INF=0x3f3f3f3f;
const int MAXN=1010;
int Gcd(int a,int b)
{
int j=-1;//even 0 odd 1
int step=0,num=2;
int f[110]={1,a,b};
while(f[num])
{
f[num+1]=f[num-1]%f[num];
num++;
}
step=num-2;
for(int i=1;i<num-1;i++)
if(f[i]>=2*f[i+1])
{
if(j>0&&(i&1)!=(j&1))
step++;
j=i;
}
return step;
}
int main()
{
int n;
while(read(n))
{
int p,q,ans=0;
for(int i=0;i<n;i++)
{
read(p);read(q);
if(q>p)
swap(p,q);
ans=max(Gcd(p,q),ans);
}
if(!(ans&1))
puts("GG");
else
puts("MM");
}
return 0;
}
POJ 1704 Georgia and Bob
StairCase博弈:
将之转化为Nim博弈,把两个棋子的距离看成一堆石子,因为如果你把左边的棋子移动任意步数,右边的棋子跟着移动相同步数就会抵消(例 2 3 3 等同于 2),这样就转换成Nim游戏了。注意,如果是奇数个的棋子,则将右边挡板当做棋子辅助运算。
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------------------------------
const int MAXN=1200;
int a[MAXN];
int main()
{
int ans,T,i,n;
read(T);
while(T--)
{
read(n);
ans=0;
for(i=0;i<n;i++)
read(a[i]);
sort(a,a+n);
for(i=n-1;i>=1;i-=2)
ans^= a[i]-a[i-1]-1;
if(n&1)
ans^=a[0]-1;
if(!ans)
puts("Bob will win");
else
puts("Georgia will win");
}
return 0;
}
HDU 1730 Northcott Game
将之转化为NIM游戏,将把每行黑白子的初始距离设为每堆石子的初始数量,当然不同的是,这个石子不仅可以取,还可以增加,但是因为这个增加的数量是有界限的(比如,白棋左移3格,黑棋左移3格,他们之间的差是不变的,因此可以认为和最初的状态是一样的,无论如何增加,一定会某一棋子到达边界,导致棋子之间的距离再无法增加)。
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------
int main()
{
int n,m,sum=0;
while(read(n)&&read(m))
{
sum=0;
for(int i=0;i<n;i++)
{
int x,y;
read(x);read(y);
sum^=(int)fabs(x-y)-1;
}
if(sum)
puts("I WIN!");
else
puts("BAD LUCK!");
}
return 0;
}
POJ 2925 Nim
简单NIM游戏的变形:
记n1^n2^n3..^n[m]=x
显然若x=0,则该局势为奇异局势,必输。
如果把ni变成x^ni,则n1^n2^...^n[i-1]^n[i+1]^...^n[m]^x^ni=0,为奇异局势。显然如果ni>x^ni,如果能ni堆中拿走ni-x^ni张牌,则一定会获胜。
所以只用统计ni中比x^ni大于的个数,结果就是先拿者获胜的种数。
<pre name="code" class="cpp">#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------------------------------
int main (){int n,t,a[1111];while(scanf("%d",&n) && n != 0){int temp=0;for(int i=0;i<n;i++){scanf("%d",&t);temp^=t;a[i]=t;}int ans=0;if(temp!=0){for(int i=0;i<n;i++){int k = 0; for(int j=0;j<n;j++) if(i!=j) k^=a[j];//只要能够取到K个,就能够根据对称原理获胜 if(k<=a[i]) ans++;}}printf("%d\n",ans);}return 0;}
POJ 1067 取石子游戏
裸Wythoff博弈:
你可以根据公式直接得出答案,也可以根据sg推出答案
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------------------------------
int main()
{
int m,n;
while(read(m)&&read(n))
{
if(m>n)
swap(m,n);
int k = n - m;
int data = floor(k*(1.0+sqrt(5.0))/2);
puts(data == m ? "0" : "1");
}
return 0;
}
HDU 1907 John
裸反NIM游戏:
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//-------------------------------------------------------------------
int main()
{
int T,n;
read(T);
int ans,a,mi;
while(T--)
{
ans=0;mi=-1;
read(n);
for(int i=0;i<n;i++)
read(a),ans^=a,mi=max(mi,a);
if(mi>1)
if(ans>0)
puts("John");
else
puts("Brother");
else
if(!ans)
puts("John");
else
puts("Brother");
}
return 0;
}
HDU 1922 a simple stone game
K倍动态减法游戏:
详见论文http://wenku.baidu.com/view/32782dea81c758f5f61f67a8.html?re=view
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
using namespace std;
template<class T>
inline bool read(T &n)
{
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
//------------------------------------------------------------------------
const int MAXN=2000010;
int a[MAXN],b[MAXN];
int n,k,cas=1;
int main()
{
int T;
read(T);
while(T--)
{
read(n);read(k);
int i=0,j=0;
a[0]=b[0]=1;
while(a[i]<n)
{
i++;
a[i]=b[i-1]+1;
while(a[j+1]*k<a[i])
j++;
if(a[j]*k<a[i])
b[i]=b[j]+a[i];
else
b[i]=a[i];
}
printf("Case %d: ",cas++);
if(a[i]==n)
puts("lose");
else
{
int ans;
while(n)
{
if(n>=a[i])
{
n-=a[i];
ans=a[i];
}
i--;
}
printf("%d\n",ans);
}
}
return 0;
}