HDU 1850 Being a Good Boy in Spring Festival

分析:

      首先假设先手的人有必赢策略。

            问题则转化为=>在任意一堆拿任意K张牌,并且所有堆的nim-sum=0(P-position)的方案总数。

                        现在我们先看一个例子(5,7,9),并假设从第一堆取任意K张牌。

                              排除第一堆牌的nim-sum为 7^9=14

                                            0111

                                          ^1001

                                          -------

                                            1110

                              如果要使所有堆的nim-sum=0成立,则第一堆取掉K张以后必定为1110,因为X^X=0。

                              所以要观察 5-k=14 k>0 成立,此例子(在第一堆取任意K张牌)明显的不成立。但并不代表在第二或第三堆取任意K张牌的解不成立。

                        现在看第二个例子(15,7,9),并假设从第一堆取任意K张牌。

                              排队第一堆牌的nim-sum为7^9=14,和第一个例子相同,所以问题变为观察 15-k=14 k>0 是否成立。

                              当然这个例子是成立的。

                        总结得出:

                              在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立的条件为:排除取掉K张牌的那一堆的nim-sum必须少于该堆牌上的数量(例子二),否则不能在此堆上取任意K张牌使所有堆的nim-sum=0成立(例子一)。

            故总方案数为 (在任意一堆拿任意K张牌,并且所有堆的nim-sum=0 成立) 的总数。

      现在分析先手的人没有必赢策略。

            因为没有必赢策略,所以a1^a2^a3^...^an=0(nim-sum=0),一定不存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。因为异或运算满足消去率,由a1^a2^...^an=a1^a2^...^ai'^...^an可以得到ai=ai'。所以将ai改变成ai'不是一个合法的移动。

 

分析完之后看代码容易明白了,PS:代码不是我的,是参考别人代码得出上述分析的。

附上 Thomas S.Ferguson 的PDF: Game Theory

      博弈论

 

ContractedBlock.gif ExpandedBlockStart.gif Code
#include <iostream>   
using namespace std;   
int main()   
ExpandedBlockStart.gifContractedBlock.gif
{   
    
int m,n,k,j,i,t;   
    
int a[102];   
    
while (scanf("%d",&n)!=EOF,n)   
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{   
        
int ans = 0;   
        
for (i=0;i<n;i++)   
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{   
            scanf(
"%d",&a[i]);   
            ans 
= ans^a[i];   
        }
   
        
//-----------------------------------   
        int counter= 0;   
        
for (i=0;i<n;i++)   
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{   
            
if (i == 0)   
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{   
                ans 
= ans^a[i];   
            }
   
            
else  
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{   
                ans 
= ans^a[i-1];   
                ans 
= ans^a[i];   
            }
   
            
if (ans < a[i])   
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{   
                counter
++;   
            }
   
        }
   
        printf(
"%d\n",counter);   
    }
   
    
return 0;   
}
  

 

转载于:https://www.cnblogs.com/jaskist/archive/2009/04/28/1445380.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值