问题描述:
有一堆物品,共n个,两人轮流从这堆物品中取,规定每次至少取一个,至多m个,获胜条件分为两种,分别是最后取光者胜或者是最后取光者败。
情形一:最后取光者胜
分析:
若n=m+1,则无论先手取走多少,后手一定可以一次性取走剩下的全部物品,这时后手胜;
若n=(m+1)*r+s,且s<=m,r为任意自然数,此时先手只要先取s个,那么后手取k个(k<=m),然后先手再取m+1-k个,也就是某一组m+1个中的剩下的物品,这时候总数成为(m+1)*(r-1),所以局面成为(m+1)的任意倍,那么在接下来的游戏过程中,无论后手取多少,先手总可以取走对应的数目从而使得总数恢复到(m+1)的整数倍,一直这样下去,先手必胜。
因此,我们总结一下,在这样的游戏规则下,求k=n%(m+1),若k不为0,则此时相当于k就是上文中提到的s,所以先手必胜,若k为0呢,则先手面临的就是当前总数为(m+1)的整数倍的情形,所以必败。
可能我们会想:为什么一定是m+1的整数倍呢?就因为我们是从n=m+1开始分析的吗?当然不是这样的,因为以(m+1)的整数倍作为判断标准可以穷尽全部情况,假设我们修改一下上文中的公式,改成:n=(m+2)*r+s(s<=m),我们可以提取出一个r来,变成:n=(m+1)*r+s+r,所以呢,此时我们完全可以将s+r整体当做新的s,或者把它称作s',当然,此时s'很有可能已经超过了m+1,但我们就可以提取出其中(m+1)的部分来,与前面的式子合并,最后就变成了n=(m+1)*(r+1)+s'-(m+1),这就又归结到了最初的那个公式当中,所以千变万化逃不出开始的公式,也就是穷尽了所有的情况~
情形二:最后取光者败
求k=(n-1)%(m+1),若k=0,则后手胜,若k!=0,则先手胜。
1.取石子(一)
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 1000 #define MAX 1<<30 #define V vector<int> using namespace std; int main(){ // freopen("D:\CbWorkspace\博弈论\取石子(一).txt","r",stdin); int T,n,m; I("%d",&T); while(T--){ I("%d%d",&n,&m); int k=n%(m+1); if(k) puts("Win"); else puts("Lose"); } return 0; }
理解:
直接套用k=n%(m+1)的公式,如果k==0,后手胜,否则先手胜。
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 1000 #define MAX 1<<30 #define V vector<int> using namespace std; int main(){ freopen("D:\CbWorkspace\博弈论\Public sale.txt","r",stdin); int m,n; while(~scanf("%d%d",&n,&m)){ int k=n%(m+1); if(n<=m){ while(k<=m){ O("%d",k); if(k!=m) O(" "); k++; } puts(""); }else{ if(k) O("%d ",k); else puts("none"); } } return 0; }
理解:
经典模型的变形