2011年8月18日,阿里巴巴程序设计公开赛A题。
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=3951
本题类似我曾今玩过的的一个NDS解密游戏《雷顿教授与魔神之笛》里的一道谜题。游戏里是给你15个围成圈的水龙头,开始它们全都是打开漏水的。接着你要跟电脑博弈,从电脑开始,双方可以选择关闭连续的两个水龙头(当然,已关的不能再打开了)也可以只选择关掉一个,最终没水龙头可关的将失败。在没学相关知识之前那迷题一直让我挺头疼的。。。
那个游戏的答案解法是,由于电脑一定会先关掉两个水龙头,接着你只要关掉剩余水龙头的中间那个,因而将剩余的水龙头分成数目相等的两个部分。那后无论电脑操作哪一部分的一或二个水龙头,你只要一样对称地关掉另一部分得水龙头。那你一定会是胜利者!
本题相当于是该迷题的一个拓展。
我们首先要分几种情况考虑:
1.当 K=1时,若N为奇数,则first wins,N为偶数则second wins。
2.当 K>=N时,first wins。
3.当 N>K>1时,情况类似上面提到过的谜题,若first的最先操作使得剩下的水龙头为偶数,如果你能把剩下的取完那就直接胜利,如果不能那就拿走中间的若干个偶数个硬币使得剩下的硬币被分为数目相等的两堆。接着对方对某堆进行操作你就对另一堆进行同样的操作,这时是second wins。first的最先操作使得剩下的水龙头为奇数时同理可证second wins。
那就OK了。
code:
#include<iostream>
using namespace std;
int T,N,K,Case=1;
int main()
{
cin>>T;
while(T--)
{
cin>>N>>K;
if(K==1)
if(N%2==0)
{
cout<<"Case "<<Case<<": second"<<endl;
Case++;
continue;
}
else
{
cout<<"Case "<<Case<<": first"<<endl;
Case++;
continue;
}
else
{
if(K>=N)
{
cout<<"Case "<<Case<<": first"<<endl;
Case++;
continue;
}
else
{
cout<<"Case "<<Case<<": second"<<endl;
Case++;
continue;
}
}
}
return 0;
}
这个问题是取子中比较简单的一种。
除此之外还有很多取子问题,比如nim取子以及它的许多变种等。