经典博弈

pku2234 Matches game!!!!!
hdu1846 brave game. if(n%(m+1)==0)n是必败点 !!!!!!
pku2484 A Funny Game. if(n>=3)n是必败点 !!!!!!
hdu1851 A Simple Game!!!!!!
for(i=1,s=0;i<=n;i++){scanf("%d%d",&m,&l);s^=m%(l+1);}
hdu1847 GoodLuck in CET-4 Everybody.if(n%3==0)n是必败点
hdu1730 Northcott Game
hdu1517 A Multiplication Game,ecjtu1038
hdu1525 Euclid's Game pku2348,ecjtu1039
hdu2147 kiki's game
hdu1907 John 取尽者败 pku3480
if(a1=a2=...=an=1) n为奇数必败,否则s=a1^a2...^an 
hdu2509 Be the Winner 取尽者败.zju1616 ,ecjtu1108
pku2068 nim-2n个人的game.ecjtu1112. 
pku1740 A New Stone Game.
pku1704 Georgia and Bob
pku2975 Nim-有多少种win的策略
hdu2176 取(m堆)石子游戏-有多少种win的策略
pku2368 Buttons
ecjtu1006 Stone Game 放(1堆)石子游戏
hdu1729 Stone Game 放(n堆)石子游戏
hdu2516 取(2倍)石子游戏 
hdu2580 a simple stone game(取k倍)
pku1082 Calendar Game
hdu1848 Fibonacci again and again 。ecjtu1113 
hdu1536(hdu1944,pku2960,ecju1110) S-Nim 
ecjtu1116 Fibonacci again
nuaa1516,ecjtu1117 质数取石子
pku2348,ecjtu1039 Euclid's Game


pku2234 Matches game


取石子游戏
两个人面队若干堆石子(或硬币,火柴,棋子)进行游戏。各堆含有
a1,a2,…,ak枚硬币。
游戏规则如下:
1. 两人轮流取子,当轮到你取子时,你不能不取
2. 取子者只能从某堆中取子,取走一堆中的任意个子
3. 最后取子者为游戏的得胜者,或当轮到你取子时,你没有子可取
    你为败者。 
:
结论1. 如果只有一堆,即k=1,则第一取子者胜;
结论2. 如果只有2堆,a1,a2, a1=a2则第2取子者胜;
    第1取子者在某堆取走c个,则 第2取子者在另1堆也取走c个,
    2堆仍然相等。
    即 第1取子者取后2堆不相等, 第2取子者取后2堆相等,最后 
    取子者是 第2取子者.
结论3. 如果只有2堆,a1,a2, a1<>a2则第1取子者胜;    
    第1取子者在多的1堆取 abs(a1-a2)个,取后2堆相等。 
定义: 如果有k堆,堆数用无序向量(a1,a2,...,ak)表示,如果第1
取子者不能获胜,则称 (a1,a2,...,ak)为必败点.
例 . k=2时,(a,a) 为必败点
结论4: 无序向量(a1,a2,...,ak),如果经过1次取子后变为必败点
则(a1,a2,...,ak)为必胜点, 无论如何取都不能变为必败点,则为
必败点 。 
例 . k=2时,(20,25) 为必胜点 ,1次取子后变为必败点(20,20)
     k=3 ,(20,20,25) 为必胜点 ,1次取子后变为必败点(20,20)
     k=2,(20,20),无论如何取都变不了必败点,(20,20) 是必败点。
     
    k=2时,相同(相等)必败,不等必胜。
    看看C语言的异或运算^
性质1.若a=b,则a^b=0;
性质2.若a<>b,则a^b<>0; 
性质3.若a^b=c,则a^c=b;
      a^a^b=a^c ==> b=a^c;
性质4.令s=a1^a2^...^an,si是a1,a2,...,an中除 ai以外的其余n-1个
      的异或值, 则
       si=s^ai 
性质5.令s=a1^a2^...^an.     
      若 s=0,则
      si=ai ,(i=1,2,...,n )
      当ai发生变化后,s<>0;
性质6.令A=(a1,a2,...,an),B=(b1,b2,...,bm,C=(a1,a2,...,an,b1,b2,...,bm).
     记为C=A+B.
     若A,B是必败点,则C是必败点 
     若A,B中有一个是必败点,另1个是必胜点,则C是必胜点.
两个必胜点之和不必是必胜点.    
       
定义:若A+B是必败点,则称A与B等价

若A==B, 则A与B等价

性质7. A+A 是必败点。

       
    3^5 =? 在C程序中 用printf("%d\n",3^5); 就知道了
     异或运算^是:相同为0,不同为1 ,不进位
     3,5的2进制数是   011,101
                     0 1 1
                     1 0 1
        ------------------------
                     1 1 0
    因此 3^5=6 =(110)2进制
利用或运算^,结论2,结论3为
结论2‘k=2,如果a1^a2=0, 则第2人胜                                     
结论3‘k=2,如果a1^a2<>0, 则第1人胜

k>2 如何 ?                                 
k=3. (a1,a2,a3) =(3,6,9) 
3^6=5, 3^6^9=5^9<>0
对 (3,6,9)取子变为 (3,6,5) ,3^6^5=5^5=0
对 (3,6,5)无论如何取子都不能使其异或为0
一般地 有
定理 令s=a1^a2^...^ak,si=s^ai,
   
     (1)若s<>0,则存在 i,将 ai缩小为si后 s=0;
     (2)若s=0,则 将任何数ai做任何缩小后 s<>0;    


#include <stdio.h>
int main()
{
    int m,n,s;//n<=1000000 
    while(scanf("%d",&m)!=EOF)
    {
        s=0;
        while(m--)
        {
            scanf("%d",&n);
            s=s^n;
        }
        if(s==0)printf("No\n");
        else printf("Yes\n");
    }
return 0;
}有m堆石子,各堆有n颗石子。

hdu1851A Simple Game
方法:
   这里采用的对每个事件中的每组数据 ,先用第一个数对比第二个数大1的数求余,再对各余数异或;
   如果得到各个余数的异或值为零则有 Agrael胜得,对应的输出"Yes",反之输出“No”;
   假设每次输入的数据为m,l;则有s=m1%(l1+1)^m2%(l2+1)^m3%(l3+1)^…………^mn%(ln+1); 
   当s=0时,输出Yes;
   当s!=0 时输出No; 
   例 m1=100 ,l1=16 
      m2=98,   l2=8    
     有 m1%(l1+1)=15;m2%(l2+1)=8;
     得 15^8!=0; 所以这里会输出 “No ”;
     怎么样理解呢?
    因为只有当异或等于0时,这里是必胜点 ;当在这一点时,对方怎么拿都不能达到必胜点;当对方拿多少时
    自己在另一处也拿多少,可以维持着处于必胜的局面;
    但是在以上这一点时,当对方 在一堆中拿中 7个后,就变成好对方的必胜点;自己就必败了;

#include<stdio.h>
int main()
{
int T,n,m,s,l;
scanf("%d",&T);
while(T--)
{
    scanf("%d",&n); 
     s=0;
    while(n--)
    { 
      scanf("%d%d",&m,&l);
      s^=m%(l+1);
    }

       
   if(s==0)printf("Yes\n");
   else printf("No\n");                 
} 
return 0; 
}

     
     
hdu1525 Euclid's Game pku2348 
    fun(int a ,int b)//a>=b
    { if( a%b==0)return 1;
      k=a/b;r=a%b;//a=k*b+r   25 7   ,7 4, 11 7
      if(k>1)return 1;      
      return 1-fun(b,r);
    } 
pku1740 A New Stone Game
a1,a2,a3…………an为必败点<=>当n为偶数时,对a1--an进行从小到大或
从大到小排序,如果有a1=a2,a3=a4,…………an-1=an,
当n为奇数时以及其它的情况则必胜。
pku1704 Georgia and Bob. 将p[]排序.
s=(p[n]-p[n-1])^(p[n-2]-p[n-3])^....^(p[2]-p[1])
   if(n%2==1 )    将 ^(p[2]-p[1])改为 ^(p[1]-p[0]),p[0]=0;

pku2975 Nim-有多少种win的策略

解题报告:
取石子问题
此题求第一次取时能够得到必胜的取法;
首先我们按照公式对所有的石子的异或值S=a1^a2^a3.....^an;
若异S==0则说明是必败点。
输出 0;
若S不等于0;
则对第i堆石子 我们求出除去第i堆石子其余石子的异或值(以 7 11 13为例)
其中 对第1堆 我们求出11^13=6 则只要把第1堆中拿去1个 变成 6个 既OK
同理 对第2堆 我们求7^13=10 则只要把第2堆中拿去1个 变成 10个 既OK
....
那么总结出
设 Si=a1^a2^a3....ai-1^ai+1^ai+2....an;    (除去第i堆石子其余石子的异或值)
若Si<ai 则说明我们可以找到一种取胜方法
for(i=1,num=0;i<=m;i++)
{ k=s^a[i];//s=a[1]^a[2]^...^a[n]
   if(k<a[i])num++;
}
ecjtu1006 Stone Game 放(1堆)石子游戏
f[d]=d*(d+1): 2,6,12,20,30,42,56
if(s<=f[d]&&s>f[d-1])s的必败点是 d-1;
s=1000,1000 的必败点是31,31的必败点是5,5的必败点是 1
hdu1729 Stone Game 放(n堆)石子游戏
s1,c1;s2,c2;...sn,cn;
bi是>=ci的最小必败点,ai=bi-ci; s=a1^a2^...^an

hdu2516 取(2倍)石子游戏 
1,2,3,5,8,13都是必败点,斐波那契数列中的数都是必败点。
hdu2580 a simple stone game(取k倍)
a[i]=i,i<=k+1是必败点,
必败点a[i+1]=a[i]+a[p],k*a[p]>=a[i],k*a[p-1]<a[i]; 
pku1082 Calendar Game
hdu1848 Fibonacci again and again .ecjtu1113 。3堆 
int F(int k)
{ int g[15],i;//计算k的等价类数E[k],
/*
k个石子,取子后变为 b[j]=k-a[j]个 
b[1],b[2],...,b[s] ,和b[j]等价的最小数是 E[b[j]]
E[b[1]],E[b[2]],...,E[b[s]] 
E[k]=   E[b[j]]中没有出现的最小数 . 
必败点等价于0;
k=fib[1],E[k]=1;
*/
for(i=0;i<15;i++)g[i]=0;
for(i=1;a[i]<=k;i++)g[E[k-a[i]]]=1; 
for(i=0;i<=k;i++)if(g[i]==0)return i; 
}

hdu1536(hdu1944,pku2960,ecju1110) S-Nim 
freopen("data1.in","r",stdin); S{2,3}
   
ecjtu1116 Fibonacci again
F[i]=0,i是必败点; F[i]=1,i是必胜点;
i是 Fibonacci数,F[i]=1;
if(F[i]==0)
{ for(j=1;fib[j]<=i;j++)if(F[i-fib[j]]==0){F[i]=1;break;}}
nuaa1516,ecjtu1117 质数取石子
原文地址<http://code.google.com/p/zldry88-acm/issues/detail?id=7>
原文地址:https://www.cnblogs.com/qianmacao/p/2458632.html