Play With Power
Masha和Stas正在玩一个游戏。在游戏的开始,给出一个定值N,同时有两个正整数A和B,初始时满足A^B≤N。
Masha先手。每一回合,玩家要将A和B的其中一个数加上1,但不能令到A^B>N,否则该玩家输。现在,Masha想知道,假如两人都使用最优策略,对于一个特定的N,不同的A、B的初始值谁将获胜呢?
这道题看上去是博弈论,但是仔细看会发现是DP或是记忆化搜索(心态爆炸)
用judge(a,b)来表示当a,b到了这种情况后的胜负,但是是你在接手这个局面后的胜负,就是说如果当
a
b
>
n
a^b>n
ab>n时,这种情况是输了,但是对于这在接手的你来说,是赢的,
我们用0来表示输了,2表示赢了,1表示平局,
存一个g[a][b]来表示
a
b
a^b
ab是否超过n,如果超过了,说明这个情况你是赢了(再理解理解),
然后,当judge(a+1,b)和judge(a,b+1)都是赢的话,对于你来说就是输了,因为你没有方法让这个情况的后面两个其中一个让你自己赢,
但如果这两个有一个是必败的话,那么现在对于你来说就是必胜的,
其他情况都是平局,即1
然后特判,当b=1的时候且a比较大,就是n-a的值,是奇数就先手赢,偶数后手赢。
以及不要忘了 long long 和快速幂,快速幂中为了防止它爆了,要在快速幂中加特盘嘤嘤嘤
#include<bits/stdc++.h>
using namespace std;
long long n;
int g[100010][40];
long long kai(long long a,long long b)
{
long long ans=1;
if (a>n) return -1;
while(b>0)
{
if(b&1) ans*=a;
a*=a;
b>>=1;
if (ans>n) return -1;
}
return ans;
}
long long judge(long long a,long long b)
{
if (b>30) return 1;
if (g[a][b]==0) g[a][b]=kai(a,b);
if (g[a][b]==-1) return 2;
long long x=judge(a+1,b),y=judge(a,b+1);
if (x==2&&y==2) return 0;
if (x==0||y==0) return 2;
return 1;
}
int main()
{
freopen("play.in","r",stdin);
freopen("play.out","w",stdout);
scanf("%lld",&n);
int t;
scanf("%d",&t);
long long ss=sqrt(n);
while (t--)
{
long long a,b;
scanf("%lld%lld",&a,&b);
int p;
if(a>ss) p=b==1?(n-a&1?2:0):0;
else p=judge(a,b);
if (p==2) printf("Masha\n");
if (p==1) printf("Missing\n");
if (p==0) printf("Stas\n");
}
}