刚开始你只有一个字符串
每次能选择一个有的字符串s,找到i,满足
s[i - 1] = s[i + 1],将其分裂成3 个字符串
s[1 ·· i - 1]; s[i]; s[i + 1 ·· |s|]
不能操作者负,求先手必胜的一个策略
初始字符串长度不超过5000
将每个字符都能操作的连续的一段作为一个游戏,状态即可表示成这一段的长度
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 5005 7 using namespace std; 8 char ch,s[maxn]; 9 int n,sg[maxn],l,idx,tmp; 10 struct DATA{ 11 int l,r,siz; 12 }list[maxn]; 13 bool ok,bo[maxn],can[maxn],flag; 14 void read(int &x){ 15 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1; 16 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar()); 17 if (ok) x=-x; 18 } 19 void calc(int k){ 20 for (int i=1,t1,t2;i<=k;i++){ 21 t1=(i-1)-1,t2=k-(i+1); 22 if (t1>0&&sg[t1]==-1) calc(t1); 23 if (t2>0&&sg[t2]==-1) calc(t2); 24 } 25 memset(bo,0,sizeof(bo)); 26 for (int i=1,t,t1,t2;i<=k;i++){ 27 t1=(i-1)-1,t2=k-(i+1),t=0; 28 if (t1>0) t^=sg[t1]; 29 if (t2>0) t^=sg[t2]; 30 bo[t]=1; 31 } 32 for (int i=0;;i++) if (!bo[i]){sg[k]=i;break;} 33 } 34 int main(){ 35 scanf("%s",s+1); 36 n=strlen(s+1); 37 for (int i=2;i<n;i++) if (s[i-1]==s[i+1]) can[i]=1; 38 for (int i=2;i<n;i++){ 39 if (can[i]&&!l) l=i; 40 if (!can[i]&&l) list[++idx]=(DATA){l,i-1,i-1-l+1},l=0; 41 } 42 if (l) list[++idx]=(DATA){l,n-1,n-1-l+1}; 43 memset(sg,-1,sizeof(sg)); 44 for (int i=1;i<=idx;i++){ 45 if (sg[list[i].siz]==-1) calc(list[i].siz); 46 tmp^=sg[list[i].siz]; 47 } 48 if (tmp){ 49 puts("First"); 50 for (int i=1,t;i<=idx;i++){ 51 t=sg[list[i].siz]; 52 for (int j=list[i].l,t1,t2,t3;j<=list[i].r;j++){ 53 t1=(j-1)-list[i].l,t2=list[i].r-(j+1),t3=0; 54 if (t1>0) t3^=sg[t1]; 55 if (t2>0) t3^=sg[t2]; 56 if (!(tmp^t^t3)){printf("%d\n",j),flag=1;break;} 57 } 58 if (flag) break; 59 } 60 } 61 else puts("Second"); 62 return 0; 63 }
时间: 2024-10-07 05:40:50