Educational Codeforces Round 123 (Rated for Div. 2)(A~C)

本文分享了三道编程竞赛中的题目及其解决方案。A题要求根据给定字符串判断能否打开所有门,通过计数当前钥匙数量解决。B题要求构造反斐波那契数列的全排列,通过逆序输出并交换元素实现。C题涉及数组和最大子列和问题,利用前缀和与动态规划找出插入元素后的最大子列和。
摘要由CSDN通过智能技术生成

开学以后就忙起来了,cf勉强当天写题,题解都跟不上了~

A.  Doors and Keys

https://codeforces.com/contest/1644/problem/A

Question:

给定长度为6的字符串,有RGB三色的门,分别需要对应的钥匙rgb来打开,还有一个限定条件,主人公按照字符串的顺序去开门,只有打开一扇门之后才能去开下一扇门,问主人公最后能不能打开所有的门

Solve:

思路比较简单,从前到后读字符串,用cnt数组把现有的钥匙存下来,当遇到对应的门之后cnt--,把钥匙消耗掉,如果遇到对应的门没有钥匙,就标记下来退出循环

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t;
string s; 
void solve()
{
	int cnt[30];
	memset(cnt,0,sizeof(cnt));
	cin >>s;
	for(int i = 0; i < 6; i++){
		//读入钥匙 
		if(s[i] == 'r' || s[i] == 'g' || s[i] == 'b') cnt[s[i] - 'a']++;
		else{
			//如果没有钥匙就输出NO 
			if(cnt[s[i] - 'A'] == 0) {
				cout <<"NO" <<endl;
				return;
			}
			else cnt[s[i] - 'A']--;
		}
	}
	cout <<"YES" <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

B.  Anti-Fibonacci Permutation       

 https://codeforces.com/contest/1644/problem/B

Question:

反斐波那契数列,构造n个1~n的全排列a,使得任给一个i都满足a[i] != a[i-1] + a[i-2]

Solve:

构造方法很多,这个题我的第一反应是要想满足a[i] != a[i-1] + a[i-2],最简单的,前面的数比后面的数大,那就肯定不会满足这个条件

所以我就顺着这个思路,逆序输出1~n,但是题目要求是n个排列啊,又不是一个,然后怎么办呢

我直接将1~n先逆序,然后在把后面的小数去做交换,交换一次输出一次

比如n=5,就输出

54321

54312

54132

51432

15432

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t, n;
int a[55];
void solve()
{
	cin >>n;
	for(int i = 1; i <= n; i++) a[i] = i;
	int pos = 1;
	//第一次的直接完全逆序输出 
	for(int i = n; i >= 1; i--) cout <<a[i] <<" ";
	cout <<endl;
	for(int i = 1; i <= n-1; i++){
		//交换元素输出n-1次 
		swap(a[pos], a[pos+1]);
		pos++;
		for(int j = n; j >= 1; j--){
			cout <<a[j] <<" ";
		}
		cout <<endl;
	}
}
 
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

C.  Increase Subarray Sums      

 https://codeforces.com/contest/1644/problem/C

Question:

先给一个长度为n的数组,然后题目想将给定的x插入数组的不同位置中

然后问你:当数组插入k个x(0 <= k <= n)时,其最大子列和是多少

Solve:

去掉插入x就是个dp基础题,虽然我不知道我但是为什么会想到模拟上,裂开

参考知乎pzr大佬的思路

max{ans[i] + min(i, k)*x} (0 <= i <= n)

首先去把原数组中选择i个连续元素的最大子列和存到ans[i]中

之后我要求添加k个x的最大子列和时,只要在ans数组中去找到ans[i]+min(i, k)*x的最大值即可,

min(i, k)是因为有i个元素的子列中最多只能添加i个x去使得子列和变大

AC Code:

代码也是借鉴pzr大佬的,前缀和数组我直接读入数据时候去维护了,max_element还是看了代码才了解的,哎,菜啊

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t, n, x;
//数据数组,前缀和数组,子列和数组 
ll a[5010], pre[5010], ans[5010]; 

void solve()
{
	cin >>n >>x;
	//计算前缀和 
    pre[0] = 0;
	for(int i = 1; i <= n; i++){
		cin >>a[i];
		pre[i] = pre[i-1] + a[i];	
	} 
	//初始化ans数组 
	for(int i = 1; i <= n; i++) ans[i] = -1e18;
	ans[0] = 0;
	//计算出i个元素构成的最大子列和ans[i] 
	for(int l = 1; l <= n; l++){
	    for(int r = l; r <= n; r++){
	        ans[r-l+1] = max(ans[r-l+1], pre[r] - pre[l-1]);
   		}
	}
	//输出k=0时的最大子列和 
    cout <<*max_element(ans,ans+1+n) <<" ";
    
    for(int i = 1; i <= n; i++){
        for(int j = 0; j <= n; j++){
            if(j >= i) ans[j] += x;
        }
        cout <<*max_element(ans,ans+1+n) <<" ";
    }
    cout <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >>t;
	while(t--){
		solve();
	}
	return 0;
}

"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值