取(2堆)石子游戏

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2622    Accepted Submission(s): 1594

Problem Description
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。如果你胜,你第1次怎样取子?
Input
输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,且a<=b。a=b=0退出。
Output
输出也有若干行,如果最后你是败者,则为0,反之,输出1,并输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。如果在任意的一堆中取走石子能胜同时在两堆中同时取走相同数量的石子也能胜,先输出取走相同数量的石子的情况.
Sample Input
1 2
5 8
4 7
2 2
0 0
Sample Output
0
1
4 7
3 5
0
1
0 0
1 2
Author
Zhousc
Source
[x y]可以转换三种状态(1)[x-k,y] (2)[x,y-k] (3)[x-k,y-k]
只要这三种里面出现至少一种输的状态 [x,y]就是必胜态  否则[x,y]必败
所以我们可以打表发现规律
打表代码
 const int N=;
int a[N][N];
int main(){
int i,j,k;
a[][]=;
for(i=;i<N;i++){
a[][i]=a[i][]=;
}
for(i=;i<N;i++){
for(j=;j<N;j++){
a[i][j]=;
for(k=;k<i;k++)
if(a[k][j]==)a[i][j]=;
for(k=;k<j;k++)
if(a[i][k]==)a[i][j]=;
for(k=;k<=min(i,j);k++)
if(a[i-k][j-k]==)a[i][j]=;
}
}
for(i=;i<;i++){
for(j=;j<;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}

输出前20组数据

我们可以发现这几种情况是输的

1 2

3 5

4 7

6 10 可以发现规律为 a=(int)(b-a)(aqrt(5)+1)/2 我也不知道规律怎么得到这个公式的

输出为1的情况 我们只需要让状态转为必败的状态就可以了

int t=(b-a)*(sqrt(5)+1)/2;

if(t<a)  假设 bb=b-(a-t)  及证明 t 和bb满足必败的条件、、

(bb+t-a-t)*(sqrt(5)+1)/2=(b-a)*(sqrt(5)+1)/2=t;

并且这种情况属于[x-k,y-k]这种  所以我们可以先判断

其他的两种自己看代码想  不想解释了

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#include<string.h>
typedef long long ll;
typedef unsigned long long LL;
using namespace std;
const int INF=0x3f3f3f3f;
const double eps=0.0000000001;
const int N=+;
const int MAX=+;
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==&&m==)break;
double b=(sqrt(5.0)+)/;
if(n==(int)(b*(m-n))){
cout<<<<endl;
continue;
}
cout<<<<endl;
int t=(int)(m-n)*b;
if(t<n)cout<<t<<" "<<t+m-n<<endl;
for(int i=;i<=m;i++){
int x=m-i;
if(x>n&&(int)(b*(x-n))==x)cout<<x<<" "<<n<<endl;
else if(x<n&&(int)(b*(n-x))==x){
cout<<x<<" "<<n<<endl;
}
}
}
}
 

最新文章

  1. Caf.CMS是一个免费的、 开源,功能齐全的CMS
  2. Excel2016右键新建工作表,打开时提示“因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。”的解决办法
  3. Sqlserver2005日志文件太大,使其减小的方法
  4. Maxdos 9.3不能引导系统进入Maxdos
  5. 【转】android shape的使用
  6. 关于Web Worker你必须知道的7件事
  7. 使用 Entity Framework
  8. zz
  9. 【KMP】Oulipo
  10. android小知识之圆角ListView
  11. 重装系统之后Hexo快速配置
  12. 设计模式--代理模式(C++版)
  13. Servlet中 End event threw exception,错误404 的解决方法
  14. T-3-java核心API-基础类
  15. Sq lServer触发器的使用
  16. 剑指Offer 50. 数组中重复的数字 (数组)
  17. 高并发高负载系统架构-php篇
  18. Java 多线程中的任务分解机制-ForkJoinPool,以及CompletableFuture
  19. C# 一些代码小结--datGirdView 保存到csv文件
  20. streamsets 包管理

热门文章

  1. Windows开发小问题集
  2. linux杀掉某个进程的脚本
  3. Python 之scrapy框架58同城招聘爬取案例
  4. Java中“==”、“compareTo()”和“equals()”的区别
  5. 类 Fabric 主机管理程序开发
  6. 洛谷——P2574 XOR的艺术
  7. RabbitMQ在Ubuntu上的环境搭建
  8. SSH免密登录的错误
  9. i++与++i的区别及效率
  10. 8.1.2 Cursor 对象