“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 I.丢史蒂芬妮
丢史蒂芬妮
发布时间: 2017年7月9日 18:17 最后更新: 2017年7月9日 21:05 时间限制: 1000ms 内存限制: 128M
有一天,空和白很无聊,决定玩盛大游戏,考虑到两个人玩,他们随便掏了一个游戏出来:在一个n∗m 的棋盘上,首先把史蒂芬妮·多拉放在左上角(1,1) 的位置。每次一个人可以将她往下,往右,往右下丢一格。当前回合,谁不能丢史蒂芬妮,谁就输了。(注意,不可以把活人丢出棋盘啦!)游戏总是空先手。
白说,这是一个垃圾游戏!我们每次把史蒂芬妮丢素数个位置吧!(换句话说,每次丢2 或3 或5 或7 或…格)空答应了。
我们都知道,空和白都很聪明,不管哪方存在一个可以必胜的最优策略,都会按照最优策略保证胜利。
玩了一局,空已经知道了这个游戏的套路,现在他决定考考你,对于给定的n 和m ,空是赢是输?如果空必胜,输出“Sora”(无引号);反之,输出“Shiro”(无引号)。
第一行有一个T表示数组组数,1<=T<100000
从第二行开始,每行为棋盘大小,n
、m
分别表示行列。
1=<n<=500
,1=<m<=500
对于每组数据,按题目要求输出。
复制
4 1 1 2 2 10 10 30 30
Shiro Shiro Shiro Sora
题目可真是坑啊,一开始没看到还可以往右下丢,dp[i][j]代表往下丢i格,往右丢j格的胜负
dp[i][j]可以想象成先在(1,1)往下方向丢t格,从(1+t,1)往(i,j)还需丢dp[i-1-t][j-1]格,那么便可以由子结构推出。
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<cmath> #include<set> #include<stack> #define ll long long #define pb push_back #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)>(y)?(y):(x)) #define cls(name,x) memset(name,x,sizeof(name)) #define pos first #define index second #define mp make_pair using namespace std; const int inf=1e9+10; const ll llinf=1e16+10; const int maxn=5e2+10; const int maxm=1e2+10; const int mod=1e9+7; int n,m; int dp[maxn][maxn]; void init() { int fac[maxn]; int k=0; bool prime[maxn]; cls(prime,0); for(int i=2;i<maxn;i++) { if(prime[i]==0) { for(int j=2;i*j<maxn;j++) prime[i*j]=1; fac[k++]=i; } } cls(dp,0); for(int i=0;i<maxn;i++) for(int j=0;j<maxn;j++) { for(int t=0;fac[t]<=i;t++) if(dp[i-fac[t]][j]==0) dp[i][j]=1; for(int t=0;fac[t]<=j;t++) if(dp[i][j-fac[t]]==0) dp[i][j]=1; for(int t=0;fac[t]<=j&&fac[t]<=i;t++) if(dp[i-fac[t]][j-fac[t]]==0) dp[i][j]=1; } } int main() { //freopen("in.txt","r",stdin); int ncas; scanf("%d",&ncas); init(); while(ncas--) { scanf("%d %d",&n,&m); printf("%s\n",dp[n-1][m-1]==0?"Shiro":"Sora"); } return 0; }