取石头游戏
两个足够聪明的人玩轮流取石头的游戏,谁取到最后一个石头谁就赢了,他们一次只能取1个、3个、7个或8个石头,写一程序判断n个石头时先取的人是输还是赢。
输入格式:
一个整数n,其值不超过10000000。
输出格式:
如果先取的人赢,请以单独一行输出1,否则输出0。
**输入样例:**
这里是3组输入。
1
10
300
**输出样例:**
上面3组数据对应的输出分别如下:
1
1
0
本题非常巧妙,我们可以先举几个例子来叙述本题.
如果有一个石子,第一个人直接拿一个,那么他就赢了,如果两个,第一个人只能拿一个,剩下的那个就是第二个人的,所以第二个人赢,3个的话第一个人依然可以全部拿完,四个的话第一个人拿一个,那么第二个人就会非常机智的拿走1个,这样就剩下了两个,就回归到了两个的情形,显然第二个人这样做他就赢了,如果第一个人拿走3个,那么依然是第二个人赢,说道这里大家应该就已经明白了这道题目的意思了,就是两个人分别发挥出250的智商,想尽方法不让剩下的那个人赢.
所以,我先给出我第一次时的代码,非常容易理解,采用的思路就是从一个石头到n个石头去试,如果第i-1或者i-3或者i-7或者i-8中有一个是第1个人输,那么第一个人就可以拿剩下到对应的数目,这样的话第二个人再拿的时候就相当于是原来的第一个人,所以他就必输了.
内存超限代码如下:
#include<iostream>
using namespace std;
bool dp[10000005];
int main() {
int n;
dp[1]=true;
dp[3]=true;
dp[5]=true;
dp[7]=true;
dp[8]=true;
cin>>n;
if(n<=8)cout<<dp[n];
else {
for(int i=9; i<=n; i++) {
if(dp[i-1]==false)dp[i]=true;
else if(dp[i-3]==false)dp[i]=true;
else if(dp[i-7]==false)dp[i]=true;
else if(dp[i-8]==false)dp[i]=true;
else dp[i]=false;
}
cout<<dp[n];
}
}
如果题目要求内存依旧是像平时那样64MB的话,这个代码可以完美的通过,然而,这道题的内存限制是1MB,下面的代码会内存超限,所以,我列举出了很多第二个人赢得数据,如下:
2 4 6 15 17 19 30 32 34 36 45 47 49 51
终于,我神奇的发现一个规律,当n%15==0或2或4或6时都是第二个人赢,其余情况那自然就是第一个人赢了,所以,写出如下代码:
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
if(n%15==0)cout<<0;
else if(n%15==2)cout<<0;
else if(n%15==4)cout<<0;
else if(n%15==6)cout<<0;
else cout<<1;
}
然后,就在这严峻的内存限制下,做出了这道题.