题意:
给定两个数字,每次数字可以进行以下两种操作:
- 数字反转
- 数字除以10,取整
每个数字每次只能进行一种操作,两个数字轮流进行,数字1会想尽办法变成数字2,数字2会尽力阻止数字1变成数字2,如果数字1可以变成数字2,那么Alice赢,否则Bob赢。
题解:
两次KMP,判断数字2和反转数字2中的一个是否是数字1的子串,如果是则Alice赢,否则Bob赢。
特判一下数字等于0的时候。
代码:
#include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <string> using namespace std; typedef long long int ll; const int maxn = 200010; char t[maxn],s[maxn],p[maxn]; int next_[maxn]; int lens, lenp; void getnext() { int i=0,j=-1; next_[0]=-1; while(i!=lenp) { if(j==-1||s[i]==s[j]) next_[++i]=++j; else j=next_[j]; } } int KMP() { int i=0,j=0,cnt=0; while(i!=lens&&j!=lenp) { if(s[i]==p[j]||j==-1) ++i,++j; else j=next_[j]; if(j==lenp) { cnt++; j=next_[j]; } } return cnt; } int main() { int T; int ans1,ans2; scanf("%d",&T); while(T--) { int is=0; memset(next_,0,sizeof(next_)); memset(p,0,sizeof(p)); memset(s,0,sizeof(s)); memset(t,0,sizeof(t)); scanf("%s%s",s,p); strcpy(t,s); lens = strlen(s); lenp = strlen(p); if(lenp==1&&p[0]=='0') { printf("Alice\n"); continue; } if(lenp>lens) { printf("Bob\n"); continue; } getnext(); ans1= KMP(); memset(s,0,sizeof(s)); for(int i=0; i<lens; i++) s[i]=t[lens-1-i]; memset(next_,0,sizeof(next_)); getnext(); ans2=KMP(); if(ans1||ans2) printf("Alice\n"); else printf("Bob\n"); } return 0; }