codeforces 305E Playing with String

刚开始你只有一个字符串
每次能选择一个有的字符串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

codeforces 305E Playing with String的相关文章

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Codeforces 56D Changing a String 编辑距离 dp

题目链接:点击打开链接 编辑距离,,== 一边dp一边记录前驱太累,,还是dp后找路径大法好 #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll int #define N 1010 char s[N], t[N]; int dp[N][N], n, m; // 0为插入 1为删除 2 3为替换 stru

Playing with String(codeforces 305E)

题意:刚开始你只有一个字符串每次能选择一个有的字符串 s,找到 i,满足s[i - 1] = s[i + 1],将其分裂成 3 个字符串s[1 · · · i - 1]; s[i]; s[i + 1 · · · len]不能操作者负,求先手必胜的一个策略初始字符串长度不超过 5000 /* 一个很暴力的转移方法设SG[i][j],每次枚举断点,但是这样是O(n^3)的. 其实我们可以发现,只有一段连续的符合s[i-1]=s[i+1]的字符串才能有贡献,所以可以设SG[len]来进行转移. */

【最短路】Codeforces 710E Generate a String

题目链接: http://codeforces.com/problemset/problem/710/E 题目大意: 问写N个字符的最小花费,写一个字符或者删除一个字符花费A,将当前的字符数量翻倍花费B. 题目思路: [动态规划][最短路] [动态规划]: 如果当前x不是2的倍数,那么一定需要单个字符增加或删除,而这个单个操作越靠后答案越优. dp(x)=a+min(dp(x-1),dp(x+1)) 如果当前x是2的倍数,那么有两种情况,一种是通过翻倍的方式获得,一种是通过累加的方式获得.只要比

(DP)codeforces - 710E Generate a String

原题链接:http://www.codeforces.com/problemset/problem/710/E 题意:一个字符串,开始长度为0,目标长度为n,长度+1或-1需要的时间为x,长度*2需要的时间为y,求0到m需要的最少时间. 分析:这题一上来直接写优先队列bfs,然后很愉快的超内存的了.就想别的方法,想了一会没想清晰,感觉可以用记忆化搜索,就往这上面一想,才发现直接dp就行了. 可以很容易发现,奇数肯定是+1或者通过*2逼近并且+1或-1得到. 而偶数只能在+1和翻倍得到. 所以在奇

CodeForces B. Obtaining the String

http://codeforces.com/contest/1015/problem/B You are given two strings ss and tt. Both strings have length nn and consist of lowercase Latin letters. The characters in the strings are numbered from 11 to nn. You can successively perform the following

[ An Ac a Day ^_^ ] CodeForces 525B Pasha and String 技巧

题意就是一次次翻转字符串 然后输出最终的字符串 暴力一发O(n*m)果然超时了 因为每次翻转的的都是a-1到对称位置 所以一个位置翻转两次等于没有操作 所以只需要记录一下len/2的位置前的操作次数 O(len/2)…… 1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<math.h> 5 #include<string.h> 6 #include&

codeforces 623A. Graph and String 构造

题目链接 给出一个图, 每个节点只有三种情况, a,b, c. a能和a, b连边, b能和a, b, c,连边, c能和b, c连边, 且无重边以及自环.给出初始的连边情况, 判断这个图是否满足条件. 由题意可以推出来b必然和其他的n-1个点都有连边, 所以初始将度数为n-1的点全都编号为b. 然后任选一个与b相连且无编号的点, 编号为1. 然后所有与1无连边的点都是3. 然后O(n^2)检查一下是否合理. #include <iostream> #include <vector>

CodeForces 710E Generate a String (DP)

题意:给定 n,x,y,表示你要建立一个长度为 n的字符串,如果你加一个字符要花费 x时间,如果你复制前面的字符要花费y时间,问你最小时间. 析:这个题,很明显的DP,dp[i]表示长度为 i 的字符串的最少花费,当 i 是偶数时,要么再加一个字符,要么从i/2中复制,如果为奇数,要么再加1个字符, 要么从i/2先加一个,再复制.即: 奇数 : dp[i] = min(dp[i-1]+x, dp[i/2+1]+y+x); 偶数 : dp[i] = min(dp[i-1]+x, dp[i/2]+y