【簡要題解】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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章