游戏
jzoj 1984
题目大意:
有很多个点,两个人每次可以取走2k2^k2k(k是一个自然数,可以自己选)个点,取走最后一个点的人胜利,现在你先选,问你是否能赢(能赢输出MaoLaoDa will win.,不能赢输出King will win.),如果可以赢,第一步最少拿几个点
输入样例#1
8
4
2
输出样例#1
MaoLaoDa will win.
2
MaoLaoDa will win.
1
MaoLaoDa will win.
2
输入样例#2
3
8
2
输出样例#2
King will win.
MaoLaoDa will win.
2
MaoLaoDa will win.
2
数据范围
0<n<10^1000002
解题思路:
我们设f[i]f[i]f[i]为现在还剩i个点,先拿是否可赢,我们可以得出f[i]=−f[i−xk]f[i]=-f[i-x^k]f[i]=−f[i−xk],我们稍微用手推一下可以发现序列:
···
1,1,-1,1,1,-1,1,1,-1,1,1,-1,1,1,-1……
···
不难发现,可以整除3的都是-1,其它都是1
然后我们还可以发现可以赢时,第一步就是整除3的余数,然后因为数据太大,我们可以用整除3的性质:把所有位置上的数字加在一起,除以3的结果和一开始一样
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int s;
int read()
{char x=getchar();int d=0;while (x<'0'||x>'9') x=getchar();while (x>='0'&&x<='9') d+=x-48,x=getchar();//数位相加return d;
}
int main()
{for (int i=1;i<=3;++i){s=read();if (s%3==0) printf("King will win.\n");//判断else printf("MaoLaoDa will win.\n%d\n",s%3);//余数}return 0;
}