【简要题解】Educational Codeforces Round 123 简要题解

【简要题解】Educational Codeforces Round 123 简要题解

老年选手打着玩。

Doors and Keys

有一个长度为6的串,由rgbRGB各出现一次组成。小写代表钥匙,大写代表门,问你是否可以走到6

直接模拟就好,然而我tmd看错题了写了个搜索还在想现在CF educational round的第一题怎么这么难了。

#include<bits/stdc++.h>
using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c==45,c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
char s[15];
int flg;

void dfs(int l,int r,int dep,int R,int G,int B){
	//fprintf(stderr,"%d %d %d %d %d %d\n",l,r,dep,R,G,B);
	if(R<0||G<0||B<0) return;
	if(l==1&&r==6) return flg=1,void();
	if(dep>15||flg) return;
	while(islower(s[r+1])){
		R+=s[r+1]=='r';
		G+=s[r+1]=='g';
		B+=s[r+1]=='b';
		++r;
	}
	while(islower(s[l-1])){
		R+=s[l-1]=='r';
		G+=s[l-1]=='g';
		B+=s[l-1]=='b';
		--l;
	}
	if(isupper(s[l-1])) dfs(l-1,r,dep+1,R-(s[l-1]=='R'),G-(s[l-1]=='G'),B-(s[l-1]=='B'));
	if(isupper(s[r+1])) dfs(l,r+1,dep+1,R-(s[r+1]=='R'),G-(s[r+1]=='G'),B-(s[r+1]=='B'));
}

int main(){
	int T=qr();
	while(T--){
		flg=0;
		scanf("%s",s+1);
		for(int t=1;t<=1;++t)
			if(islower(s[t]))
				dfs(t,t,0,s[t]=='r',s[t]=='g',s[t]=='b');
		if(flg) puts("YES");
		else puts("NO");
	}
	return 0;
}

Anti-Fibonacci Permutation

一个排列是反斐波那契的,当且仅当\(\forall i \ge 3,p_{i-1}+p_{i-2}\not = p_i\),对于一个\(n\),请你输出\(n\)个反斐波那契排列

排列小于\(10\)先搜索一下然后打表。

排列大于\(10\)考虑把\(1\quad 2\quad 3\)换成\(3\quad 1 \quad 2\),然后对于排列最后\(5\)个数进行next_permutation,一定可以搞出很多出来,选出其中\(n\)个即可,复杂度\(O(5!n)\)

#include<bits/stdc++.h>
using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c==45,c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}

const int maxn=150;
int a[maxn];
string ans[]={"","","","1 3 2 \n2 3 1 \n3 1 2 \n","1 2 4 3 \n1 3 2 4 \n1 4 2 3 \n1 4 3 2 \n","1 2 4 3 5 \n1 2 4 5 3 \n1 2 5 3 4 \n1 2 5 4 3 \n1 3 2 4 5 \n","1 2 4 3 5 6 \n1 2 4 3 6 5 \n1 2 4 5 3 6 \n1 2 4 5 6 3 \n1 2 5 3 4 6 \n1 2 5 3 6 4 \n","1 2 4 3 5 6 7 \n1 2 4 3 5 7 6 \n1 2 4 3 6 5 7 \n1 2 4 3 6 7 5 \n1 2 4 5 3 6 7 \n1 2 4 5 3 7 6 \n1 2 4 5 6 3 7 \n","1 2 4 3 5 6 7 8 \n1 2 4 3 5 6 8 7 \n1 2 4 3 5 7 6 8 \n1 2 4 3 5 7 8 6 \n1 2 4 3 6 5 7 8 \n1 2 4 3 6 5 8 7 \n1 2 4 3 6 7 5 8 \n1 2 4 3 6 7 8 5 \n","1 2 4 3 5 6 7 8 9 \n1 2 4 3 5 6 7 9 8 \n1 2 4 3 5 6 8 7 9 \n1 2 4 3 5 6 8 9 7 \n1 2 4 3 5 6 9 7 8 \n1 2 4 3 5 6 9 8 7 \n1 2 4 3 5 7 6 8 9 \n1 2 4 3 5 7 6 9 8 \n1 2 4 3 5 7 8 6 9 \n","1 2 4 3 5 6 7 8 9 10 \n1 2 4 3 5 6 7 8 10 9 \n1 2 4 3 5 6 7 9 8 10 \n1 2 4 3 5 6 7 9 10 8 \n1 2 4 3 5 6 7 10 8 9 \n1 2 4 3 5 6 7 10 9 8 \n1 2 4 3 5 6 8 7 9 10 \n1 2 4 3 5 6 8 7 10 9 \n1 2 4 3 5 6 8 9 7 10 \n1 2 4 3 5 6 8 9 10 7 \n"};

int main(){
	int T=qr();
	while(T--){
		int n=qr();
		if(n<=10) printf("%s",ans[n].c_str());
		else{
			for(int t=1;t<=n;++t) a[t]=t;
			a[1]=3; a[2]=1; a[3]=2;
			int cnt=0;
			do{
				int flg=1;
				for(int t=3;t<=n;++t)
					if(a[t-2]+a[t-1]==a[t])
						flg=0,t=n;
				if(flg){
					++cnt;
					for(int t=1;t<=n;++t)
						printf("%d ",a[t]);
					putchar('\n');
				}
			}while(next_permutation(a+n-5+1,a+n+1)&&cnt<n);
			if(cnt!=n){
				//cerr<<"qwq";
				return 0;
			}
		}
	}
	return 0;
}

Increase Subarray Sums

给定一个序列和一个数\(x\),设\(f(k)\)表示选取序列中\(k\)个数加上\(x\)然后求出的最大子段和。输出\(f(0)\dots f(n)\)

\(Max[i]\)表示长度为\(i\)的子段中的最大子段和,然后\(f(k)=\max(Max[i]+\min(i,k)\times x)\),复杂度\(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c==45,c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
typedef long long ll;
const int maxn=5005;
int a[maxn];
ll Max[maxn];

int main(){
	int T=qr();
	while(T--){
		ll n=qr(),x=qr();
		for(int t=1;t<=n;++t) a[t]=qr();
		for(int t=1;t<=n;++t) Max[t]=-1e12;
		for(int t=1;t<=n;++t){
			int s=0;
			for(int i=t;i<=n;++i){
				s+=a[i];
				Max[i-t+1]=max<ll>(Max[i-t+1],s);
			}
		}
		for(int k=0;k<=n;++k){
			ll ans=0;
			for(int i=0;i<=n;++i)
				ans=max<ll>(ans,min(k,i)*x+Max[i]);
			printf("%lld ",ans);
		}
		putchar('\n');
	}
	return 0;
}
 

Cross Coloring

有一个\(n\times m\)的格子图,初始是白色。你要进行\(q\)次操作,每次操作你要选择\(k\)种(k种都不是白色)颜色中一个颜色,然后\(x_i\)行和\(y_i\)列就被染上这个颜色。问染色方案数。

答案\(=\)(在最终染色方案中有用的染色操作)\(^k\)

考虑一个操作\(i\)是没用的(即被其他染色操作完全覆盖了),当且仅当

  • 对于某个行,\(j>i,x_j=x_i\) 或者 在之后所有列都被染过一次颜色。

  • 对于某个列,\(j>i,y_j=y_i\) 或者 在之后所有行都被染过一次颜色了。

复杂度\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c==45,c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
const int maxn=2e5+5;
const int mod=998244353;
typedef long long ll;

int ksm(const int&ba,const int&p){
	int ret=1;
	for(int t=p,b=ba;t;t>>=1,b=1ll*b*b%mod)
		if(t&1) ret=1ll*ret*b%mod;
	return ret;
}
int row[maxn],col[maxn];
pair<int,int> que[maxn];

int main(){
	int T=qr();
	while(T--){
		int n=qr(),m=qr(),k=qr(),Q=qr(),fcnt=Q,cntr=0,cntc=0;
		for(int t=1;t<=n;++t) row[t]=0;
		for(int t=1;t<=m;++t) col[t]=0;
		for(int t=1;t<=Q;++t) que[t].first=qr(),que[t].second=qr();
		for(int t=Q;t;--t){
			int cnt=0;
			if(row[que[t].first]||cntc==m) ++cnt;
			if(!row[que[t].first]) row[que[t].first]=t,++cntr;
 			if(col[que[t].second]||cntr==n) ++cnt;
			if(!col[que[t].second]) col[que[t].second]=t,++cntc;
			if(cnt==2) --fcnt;
		}
		int ans=ksm(k,fcnt);
		printf("%d\n",ans);
	}
	return 0;
}

Expand the Path

有一个机器人,遵循DR规则,即遇到一个D就往下走一格,遇到一个R就往右走一格。现在初始给你一个DR串,你每次可以选择任何一个字母,比如D,把他变成DD。问你可以经过多少格?一个格子可以被经过,当且仅当存在一种操作该DR串的方式,使得机器人在不走出地图的情况下经过这个格子。

考虑那些走不到的格子,是原DR串走出的轮廓线下方或者右方,模拟一下即可。(有事待会再详细更博,未完待续)

#include<bits/stdc++.h>
using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c==45,c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
typedef long long ll;
const int maxn=2e5+5;
char s[maxn];

int main(){
	int T=qr();
	while(T--){
		int n=qr();
		scanf("%s",s+1);
		int L=strlen(s+1);
		int flg=1;
		for(int t=2;t<=L;++t)
			if(s[t]!=s[t-1])
				flg=0;
		if(flg){
			printf("%d\n",n);
			continue;
		}
		ll ans=1ll*n*n,sav=0,lastcnt=0;
		for(int t=L;t;--t){
			if(s[t]=='D') ++sav,lastcnt=0;
			if(s[t]=='R') ans-=sav,++lastcnt;
		}
		if(s[1]=='R') ans-=(n-1-sav)*lastcnt;
		sav=0;
		for(int t=L;t;--t){
			if(s[t]=='R') ++sav,lastcnt=0;
			if(s[t]=='D') ans-=sav,++lastcnt;
		}
		if(s[1]=='D') ans-=(n-1-sav)*lastcnt;
		printf("%lld\n",ans);
		for(int t=1;t<=L;++t) s[t]=0;
	}
	return 0;
}
posted @ 2022-02-23 11:36  谁是鸽王  阅读(49)  评论(0编辑  收藏  举报