巴什博弈 (例:HDU1846&HDU1847&HDU2188&HDU2149)

版权声明:本文为博主原创文章,转载时请注明原文地址=w=,希望对您有所帮助 https://blog.csdn.net/Eirlys_North/article/details/53063491

巴什博弈:

只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。

    显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。换句话说,也就是面对这个局面的先手必输(谁面对这个局面谁一定输)=。=

因此我们发现了如何取胜的法则:

如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。

总之,要保持给对手留下(m+1)的倍数,就能最后获胜。

所以,只要开局的时候n%(m+1)!=0,先取者一定获胜。

巴什博弈的一个最重要的特征就是只有一堆。然后就在其中改,

要么在范围内不规定个数,要么就规定只能取几个,再要么就倒过来,属于最简单的博弈

 当然这种题目可以直接先枚举前面几个数,就能找到规律啦


扫描二维码关注公众号,回复: 3772652 查看本文章

HDU1846

巴什博奕裸的模板题

var
    t,n,m               :longint;
function work(n,m:longint):string;
begin
   if (n mod (m+1)=0) then exit('second');
   exit('first'); 
end;

begin
   read(t);
   while (t>0) do
   begin
      dec(t);
      read(n,m);
      writeln(work(n,m));
   end;
end.

HDU1847

自行找规律,从1开始模拟试一试

var
    n                   :longint;
    f                   :array[1..1005] of boolean;
function work(n:longint):string;
begin
   if f[n] then exit('Kiki');
   if (n mod 3=0) then exit('Cici');
   exit('Kiki');
end;

begin
   fillchar(f,sizeof(f),false);
   f[1]:=true;f[2]:=true;f[4]:=true;f[8]:=true;f[16]:=true;
   f[32]:=true;f[64]:=true;f[128]:=true;f[256]:=true;
   f[512]:=true; 
   read(n);
   while not EOF do
   begin
      writeln(work(n));
      read(n);
   end;
end.

HDU2188

同样是裸的模板题=w=

var
    t,n,m               :longint;
    i                   :longint;
begin
   read(t);
   for i:=1 to t do
   begin
      read(n,m);
      if (m>=n) then writeln('Grass') else
      begin
         if (n mod (m+1)=0) then writeln('Rabbit')
          else writeln('Grass'); 
      end;
   end;
end.

HDU2149

因为要输出第一次的具体方案,详解见上分析

var
    n,m                 :longint;
function min(a,b:longint):Longint;
begin
   if a<b then exit(a) else exit(b);
end;

procedure work(n,m:longint);
var
      i:longint;
      t:longint;
begin
   if (n mod (m+1)=0) then
   begin
      writeln('none');exit;
   end;
   //
   if (m>=n) then
   begin
   for i:=n to m-1 do write(i,' ');writeln(m);exit;
   end;
   //
   t:=n mod (m+1);
   //
   writeln(t);  //保证留给对手n=k*(m+1)
end;

begin
   read(n,m);
   while not EOF do
   begin
      work(n,m);
      read(n,m);
   end;
end.
——by Eirlys

转载请注明出处=w=


猜你喜欢

转载自blog.csdn.net/Eirlys_North/article/details/53063491