ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21.06.06 训练赛

2021-06-14 15:33:28  阅读:155  来源: 互联网

标签:ch 06 int sum pos 21.06 训练赛 序列 include


B Reverse Game

题意

​ 一个博弈游戏,开始给定一个01字符串,每次操作可以选择如下形式中的子串:10,110,100,1010。选定后将其翻转,即为一次操作。双方轮流操作,某方不能操作即失败。Alice先手,对于给定的字符串,谁胜?

题解

签到。
首先显然,最终局面一定是如00000...11111...的形式。如果我们把相邻两个数交换记为一次操作,那么题意所说的操作可以分解为一或两次操作,如10变为01为1次操作,100变为001为2两次操作。设\(sum\)={变成最终局面需要执行的操作次数},那么每次操作要么让\(sum-1\),要么让\(sum-2\)。同时我们可以发现,在\(sum \geqslant 3\)的时候,先手如果让\(sum-1\),后手必然能够让\(sum-2\)。反之亦然。这就是经典博弈问题之一了。\(Ans=(sum\:mod\:3==0?Bob: Alice)\)。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6;
char S[maxn+8];
 
int main()
{
	  scanf("%s",S+1);
	  int tmp=0,cnt=0,len=strlen(S+1);
	  for (int i=1;i<=len;i++)
		    {
			      if (S[i]=='1') tmp++;
			      else cnt=(cnt+tmp)%3;
		    }
	  cnt?puts("Alice"):puts("Bob");
	  return 0;
}

E Divisible by 3

题意

给你一个序列\([a_i]\),问有多少子序列\([l,r]\)满足\(weight_{l,r}=\sum_{l \leqslant i\leqslant j\leqslant r}a_i \times a_j \equiv 0\pmod3\)。

题解

签到。

定义\(f_{i,j,k}\)为有多少个以i为结尾的子序列,满足\(weight=j\ mod\ 3\),且序列和为\(k\)那么转移就很简单了。具体看代码。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=5e5;
int n;
ll f[maxn+8][3][3];
int a[maxn+8];

int read()
{
	  int x=0,f=1;char ch=getchar();
	  for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
	  for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	  return x*f;
}

int main()
{
	  n=read();
	  for (int i=1;i<=n;i++) a[i]=read()%3;
	  for (int i=1;i<=n;i++)
		    {
			      for (int j=0;j<3;j++)
						for (int k=0;k<3;k++)
						  f[i][(j+k*a[i])%3][(k+a[i])%3]+=f[i-1][j][k];
			      f[i][0][a[i]]++;
		    }
	  ll ans=0;
	  for (int i=1;i<=n;i++) for (int j=0;j<3;j++) ans+=f[i][0][j];
	  printf("%lld\n",ans);
	  return 0;
}

M Mistake

题意

给定n个点m条边的有向无环图,给一个n*k的序列,保证每个\(1 \leqslant i \leqslant n\)都在序列中出现k次。将这个序列划分为k个序列(划分后序列中的数相对顺序不变),满足每个序列都是这张有向无环图的合法拓扑序。保证存在合法构造。

题解

看起来很难实际很sb的一题。

首先为了满足拓扑序,其实就是对于序列给出了一些诸如x必须在y之前出现的限制。那么我们考虑这样构造:对于某一个位置上的数x,它属于的编组序号就是数x到这个位置出现的次数。我们利用反证法证明正确性:如果存在两个数x,y和他们第i次出现的位置\(pos_{x,i}、pos_{y,i}\),如果x必须出现在y之前而\(pos_{x,i}>pos_{y,i}\),那么可知将\(pos_{x,i}\)也不能和\(pos_{y,i}\)之前的y放在同一编组,同时如果跟\(pos_{y,i}\)之后的某一个\(pos_{y,j}\)放在同一编组,那么\(pos_{y,i}\)又会和\(pos_{x,j}\)冲突(因为\(i<j\),由构造方法可知\(pos_{x,j} > pos_{x,i} > pos_{y,i}\))。所以存在合法的构造当且仅当这种构造方法合法。

代码实现就简单了(所以和图有什么关系)。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5e5;
int id[maxn+8];
int n,k,m;

int read()
{
	  int x=0,f=1;char ch=getchar();
	  for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
	  for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	  return x*f;
}

int main()
{
	  n=read(),k=read(),m=read();
	  for (int i=1;i<=m;i++) {read(),read();}
	  for (int i=1;i<=n*k;i++)
		    {
			      int x=read();
			      printf("%d ",++id[x]);
		    }
	  return 0;
}

标签:ch,06,int,sum,pos,21.06,训练赛,序列,include
来源: https://www.cnblogs.com/Alseo_Roplyer/p/14882522.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有