Codeforces Round #534 (Div. 2)
B. Game with string
题意:
给出一个字符串s只包括小写字母。当轮到一个玩家的时候,他可以选择两个连续且相等的字母并且删除它。当一个玩家没得删的时候他就输了。
题解:
乍一看有点懵,像dp,但是观察一下就发现输赢和顺序无关,只跟能组成相同的对数量有关,这个数量是一定的。那么我们用栈扫一遍就好了。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <stack> 6 7 using namespace std; 8 const int maxn=1e5+100; 9 char s[maxn]; 10 int n; 11 stack<char>S; 12 int ans; 13 int main(){ 14 scanf("%s",s); 15 n=strlen(s); 16 for(int i=0;i<n;i++){ 17 if(!S.empty()&&S.top()==s[i]){ 18 S.pop(); 19 ans++; 20 }else{ 21 S.push(s[i]); 22 } 23 } 24 if(ans%2){ 25 printf("Yes\n"); 26 }else{ 27 printf("No\n"); 28 } 29 return 0; 30 }
C. Grid game
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 const int maxn=1000+10; 8 char s[maxn]; 9 int n; 10 int main(){ 11 scanf("%s",s); 12 n=strlen(s); 13 int a=0,b=0; 14 for(int i=0;i<n;i++){ 15 if(s[i]=='0'){ 16 a=a%4+1; 17 printf("3 %d\n",a); 18 }else{ 19 b=b%2+1; 20 printf("1 %d\n",b*2-1); 21 } 22 } 23 return 0; 24 }
D. Game with modulo
题意:交互题。
V和P要玩一个游戏,P有一些正整数a,V要用下面的问题来猜这个数字a。他可以问(x,y),P会回答他:
1.'x',如果x mod a >= y mod a
2.'y',如果 x mod a < y mod a
V需要在60次问题内猜到数字a。保证a<=1e9.
题解:
首先询问0,1。如果返回x,那么a一定是1.如果返回y那么去询问1 2如果返回y再询问2 4然后4 8,8 16。直到返回x,则证明a一定在x和y之间。然后二分[x,y]这个区间。
这种办法我也没想到,看了答案后可以推一下发现可以很容易推出y=2*x.
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 const int Max=1e9; 8 9 string com; 10 11 int main(){ 12 while(cin>>com){ 13 if(com=="end")break; 14 if(com=="mistake")break; 15 if(com=="start"){ 16 char c; 17 printf("? 0 1\n"); 18 fflush(stdout); 19 scanf(" %c",&c); 20 if(c=='x'){ 21 printf("! 1\n"); 22 fflush(stdout); 23 continue; 24 }else{ 25 int x=1,y=2; 26 printf("? %d %d\n",x,y); 27 fflush(stdout); 28 while(scanf(" %c",&c)){ 29 if(c=='x'){ 30 break; 31 } 32 x=y,y=2*y; 33 printf("? %d %d\n",x,y); 34 fflush(stdout); 35 } 36 int l=x,r=y; 37 int ans=0; 38 for(int j=1;j<=29;j++){ 39 int mid=l+(r-l)/2; 40 printf("? %d %d\n",mid,r); 41 fflush(stdout); 42 scanf(" %c",&c); 43 if(c=='x'){ 44 l=mid; 45 }else{ 46 r=mid; 47 } 48 } 49 printf("! %d\n",max(l,r)); 50 fflush(stdout); 51 } 52 } 53 } 54 // fflush(stdout); 55 return 0; 56 }
E. Johnny Solving
题意:
给出一张连通图,不存在自环和重边,有n个结点和m条边,每个点的度数至少为3,给出一个参数k,若存在长度大于等于n/k的路径,则输出PATH并将路径输出,若存在k个满足周长不被3整除的环,且每一个环都存在一个只属于只属于这个环的点则输出CYCLES,并将k个环输出。
题解:下面是翻译自官方题解。。
从1结点开始建dfs树,然后确定这颗生成树的深度为depth。如果深度最少为n/k,那么我们就可以打印从根结点到最深结点的路径。否则的话,在dfs树中至少存在k+1个叶子结点。(想一想为什么,其实比较显然,也很好证明)。现在考虑dfs树中的一个叶子结点v,这个叶子结点至少有两条反向边,我们定义这两条反向边连向的祖先为x和y。显然我们有三个环,x到v,y到v,和x到y加上v。他们的长度分别是d(v,x)+1,d(v,y)+1,和d(x,y)+2.
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 7 using namespace std; 8 const int maxn=25e4+100; 9 const int maxm=5e5+100; 10 int head[maxn],Next[2*maxm],to[2*maxm]; 11 int n,m,sz,k,goal,cir; 12 vector<int>path; 13 void init(){ 14 sz=0; 15 memset(head,-1,sizeof(head)); 16 } 17 void add_edge(int a,int b){ 18 ++sz; 19 to[sz]=b;Next[sz]=head[a];head[a]=sz; 20 } 21 int vis[maxn]; 22 bool find_path(int u,int fa){ 23 vis[u]=1; 24 path.push_back(u); 25 if(path.size()>goal) 26 return true; 27 for(int i=head[u];i!=-1;i=Next[i]){ 28 int v=to[i]; 29 if(vis[v])continue; 30 if(find_path(v,u)) 31 return true; 32 } 33 path.pop_back(); 34 return false; 35 } 36 int depth[maxn]; 37 void dfs(int u,int fa){ 38 vis[u]=1; 39 depth[u]=path.size(); 40 path.push_back(u); 41 int flag=0; 42 for(int i=head[u];i!=-1;i=Next[i]){ 43 int v=to[i]; 44 if(!vis[v]){flag=1;break;} 45 } 46 if(flag){ 47 for(int i=head[u];i!=-1;i=Next[i]){ 48 int v=to[i]; 49 if(!vis[v]) 50 dfs(v,u); 51 } 52 }else{ 53 if(cir){ 54 cir--; 55 int fax=-1,fay=-1; 56 for(int i=head[u];i!=-1;i=Next[i]){ 57 int v=to[i]; 58 if(v==fa)continue; 59 if(fax==-1)fax=v; 60 else if(fay==-1){fay=v;break;} 61 } 62 if(depth[fax]<depth[fay])swap(fax,fay); 63 int ori=-1; 64 if((depth[u]-depth[fax]+1)%3)ori=fax; 65 if((depth[u]-depth[fay]+1)%3)ori=fay; 66 if(ori==-1){ 67 printf("%d\n",depth[fax]-depth[fay]+2); 68 printf("%d ",u); 69 for(int i=depth[fax];i>=depth[fay];i--){ 70 printf("%d ",path[i]); 71 } 72 printf("\n"); 73 }else{ 74 printf("%d\n",depth[u]-depth[ori]+1); 75 for(int i=depth[u];i>=depth[ori];i--){ 76 printf("%d ",path[i]); 77 } 78 printf("\n"); 79 } 80 } 81 } 82 path.pop_back(); 83 } 84 85 int main(){ 86 scanf("%d%d%d",&n,&m,&k); 87 goal=n/k; 88 if(n%k)goal++; 89 init(); 90 for(int i=1;i<=m;i++){ 91 int u,v; 92 scanf("%d%d",&u,&v); 93 add_edge(u,v); 94 add_edge(v,u); 95 } 96 if(find_path(1,0)){ 97 printf("PATH\n"); 98 printf("%d\n",path.size()); 99 for(int i=0;i<path.size();i++){ 100 printf("%d ",path[i]); 101 } 102 }else{ 103 cir=k; 104 memset(vis,0,sizeof(vis)); 105 path.clear(); 106 printf("CYCLES\n"); 107 dfs(1,0); 108 } 109 return 0; 110 }