hdu 2486/2580 / poj 3922 A simple stone game 博弈论

本文探讨了一类组合游戏问题——K倍动态减法游戏的必败态规律及求解策略,通过构造数列来解析游戏过程,实现对游戏胜负情况的预测。

思路:

这就是K倍动态减法游戏,可以参考曹钦翔从“k倍动态减法游戏”出发探究一类组合游戏问题的论文。
首先k=1的时候,必败态是2^i,因为我们把数二进制分解后,拿掉最后一个1,那么会导致对方永远也取不完,我们可以拿到最后一个1.
k=2的时候,必败态是斐波那契数列,因为任何一个整数n都可以写成两项斐波那契数的和,所以我们拿掉1,对方永远取不完高两位的数。
k的时候我们必须构造数列,将n写成数列中一些项的和,使得这些被取到的项的相邻两个倍数差距>k 那么每次去掉最后一个1 还是符合上面的条件。设这个数列已经被构造了i 项,第 i 项为a[ i ],前 i 项可以完美对1..b[ i ] 编码使得每个编码的任意两项倍数>K 那么有

a[ i+1 ] = b[ i ] + 1;这是显然的 因为b[ i ] + 1没法构造出来,只能新建一项表示

然后计算b[ i+1] 既然要使用 a[ i+1 ] 那么下一项最多只能是某个 a[ t ] 使得 a[ t ] * K < a[ i+1 ] 于是

b[ i ] = b[ t ] + a[ i+1 ]

然后判断n是否在这个数列里面

如果在,那么先手必败。否则不停的减掉数列a中的项构造出n的分解,最后一位就是了。

代码如下:

 

 1 #include<cstdio>
 2 int a[1000000],b[1000000];
 3 int main()
 4 {
 5     int i,j,t,n,k,c=0,ans;
 6     scanf("%d",&t);
 7     while(t--){
 8         scanf("%d%d",&n,&k);
 9         i=j=0;
10         a[0]=b[0]=1;
11         while(a[i]<n){
12             i++;
13             a[i]=b[i-1]+1;
14             while(a[j+1]*k<a[i]) j++;
15             if(a[j]*k<a[i]) b[i]=b[j]+a[i];
16             else b[i]=a[i];
17         }
18         printf("Case %d: ",++c);
19         if(a[i]==n) puts("lose");
20         else{
21             while(n){
22                 if(n>=a[i]){
23                     n-=a[i];
24                     ans=a[i];
25                 }
26                 i--;
27             }
28             printf("%d\n",ans);
29         }
30     }
31     return 0;
32 }
View Code

 

 

 

转载于:https://www.cnblogs.com/xin-hua/p/3273360.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值