【Day2P3,头痛的博弈】取石子游戏 题解

      OI林林总总的题目中,本人最头痛的就是传说中的博弈问题。什么叫最优选择?咋的会有什么必胜策略?晕啊/o\...

      悲剧的是,C老师的测试题中偏偏加了这种题…对于只会输出“0”的我来说(当然偶数只能取1我也发现了~),题解中那句“本题一定有解”注定了我那次测试悲惨的命运…

 

 

【题目描述】
这里有K块石头(
3<=k<=10^10),两个人轮流来取这些石头。每次最多取L块(L>0),最少
取1块。对于输入的k,判断是否存在一个L,使得第二个取的人有必胜的策略,如果有,输出
最小的L;如果没有,则输出0。
【输入格式】
第一行为一个正整数T,表示数据的组数。接下来T行,每行一个正整数K(
1<=T<=1000)
【输出格式】
输出共T行,为T组数据的解答,每行为满足条件的最小L或0
【样例输入】
1
3
【样例输出】
2

 

      据同学说,很Easy的一道博弈…觉得无从下手的童鞋们,可以往下看。

      很显然,如果k是一个偶数,则结果一定是1(也就是一个一个的取)。然而偶数呢?

      简单分析,如果每次取k-1个,那么第二个取的人一定会赢。但是题目要求输出的是最小解。有了前面分析的结果,我们可以将题目进行转化。

      我们有15个石子。由于我们知道了“每次取k-1”这一必胜策略,那么,我们可以将整体必胜转化为局部必胜,也就是说,将他们分组。

      首先把他们分成三组。那么每次取4,则第二个取的必胜。

      其次我们可以把他们分成5组,这样每次取两个,第二个取的人必胜。

      因为题目要求输出最小的L,那么我们的任务就变成,找到k的最小的约数。这也就是偶数的答案是1的原因。

      这样主要的困难就是找约数。可以证明,最小的约数一定是一个质数。数据范围很大,那么我们可以打一个1到10^5的质数表。嗯,就这样了。

 

参考代码(省略质数表):

 

1 program game;
2 const
3 z:array[1..9592]of longint=(质数表);
4 var
5 i,j:longint;
6 k,p,t:int64;
7 begin
8 readln(t);
9 for i:=1 to t do
10 begin
11 p:=0;
12 readln(k);
13 for j:=1 to 9592 do //简单的枚举
14 if k mod z[j]=0 then
15 begin
16 p:=j;
17 break;
18 end;
19 if p=0 then writeln(k-1) //处理大质数
20 else writeln(z[p]-1);
21 end;
22 END.

(saltless原创,转载请注明出处)

posted on 2010-10-13 12:17  saltless  阅读(790)  评论(0编辑  收藏  举报

导航