Codeforces Round #821 (Div. 2)ABC题解

传送门 :Dashboard - Codeforces Round #821 (Div. 2) - Codeforcesicon-default.png?t=M85Bhttps://codeforces.com/contest/1733A:

A

Consecutive Sum

题意大致为给定t组测试用例。每组给有n个数的数组a和一个k,你最多可以选择以下k次操作:

        从数组a中选择下标为 i 和 j 的两个数

        如果 i % k == j % k的话,可以选择交换 a[i] 和 a[j] 的值.

找到一个连续的字串,其长度为k,且字串和最大。

题解:

从输入的时候,就将取模后最大的数存到下标为 0~k - 1的数组中,1 ~ k-1正好是 任何正整数模k的所有可能结果,所以,当输入完时,数组中 前 k 个元素中,每个元素的值就是每个下标等于 i % k的数的最大的那一个然后把前k个数加起来输出即可。

ac代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e2 + 10;
int t,k,n,x;
LL sum;
int a[N];
int main()
{
	cin >> t;
	while(t -- )
	{
		sum = 0;
		cin >> n >> k;
		for(int i = 1;i <= n;i ++ )
		{
			cin >> x;
			a[i % k] = max(a[i % k],x); //   前1 - k个元素中只存最大的。 
		}
		for(int i = 0;i < k;i ++ )
			sum += a[i];
		cout << sum << endl;
		fill(a, a + k, 0);
	}
	return 0;
}

B. Rule of League

B

Rule of League

 

inputCopy
5
5 2 0
8 1 2
3 0 0
2 0 1
6 3 0
outputCopy
1 1 4 4
-1
-1
2 
-1

 

题目大意:

有n个人打羽毛球比赛,第1个人和第2个人先打,胜者和3打,和3的胜者再和4打...直到和第n个人打完,赢的人就是胜者。

题目给定,每个人只会赢得 x 次比赛或者 y 次比赛。

找到比赛的胜者,并输出每场比赛胜者的编号,多个情况随便输出一个即可。若给定的条件使得不会有胜者,使条件不成立则输出 -1 .

给定t组测试样例和 n x y;

输出每场比赛的获胜者或者 - 1;

题解:

输赢总和一样,总共赢多少场就会总共输多少场。每场比赛都是一个新的人和上一场的获胜者,或者第一个人和第二个人,所以肯定会至少有一个人一场都没赢,所以x和y至少有一个为0;若最终有获胜者,则肯定会有人赢,所以,x,y只能有一个是0,不能同时为0。

现在看情况交换x和y的值,让大的数是x,小的数是y,所以x和y肯定是,x 非0,是一个人获胜的场数,y = 0。

总共只有n个人,所以会打 n - 1场比赛,也就是肯定一共会赢 n - 1次,也输n - 1次,因为每个人只会赢0次和赢 x 次,所以 n - 1一定是x的倍数,(n - 1)% x 一定等于0。

不符合上诉情况的直接输出 -1 continue;

否则:

让第一个人输,剩下 n - 1个人正好可以整除 x,从第二个人开始,输出x次 i (2 <= i <= n),然后i再加个x,知道i等于n为止.

AC代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,x,y;
int main()
{
	for(cin >> t;t -- ;)
	{
		cin >> n >> x >> y;
		if(x < y)                // x是胜场,y是0 
			swap(x,y);
		if(!x || y || (n - 1) % x)
		{
			cout << "-1" << endl;
			continue;	
		}
		for(int i = 2;i <= n;i += x)
		{
			for(int j = 0;j < x;j ++ )
			{
				cout << i << " ";
			}	
		}
		cout << endl;
			
		
	}
	return 0;
}

C:

C

Parity Shuffle Sorting

Example
inputCopy
3
2
7 8
5
1 1000000000 3 0 5
1
0
outputCopy
0
2
3 4
1 2
0

 

题目大意:

给定有n个非负整数的数组a,最多执行 n 次以下操作:

选定两个下标 l 和 r;

如果a[l] + a[r] 的和 为奇数,则让 a[r] = a[l] (前面赋值给后面), 如果和为偶数,则让 a[l] =  a[r] (后面赋值给前面)

最多执行 n 次以上操作,使得a数组变成一个非递减的序列。

PS:题目保证一定有解。并且题目让求的 不是需要执行的最少次数,而是找到任何一个满足执行次数小于等于n的情况,输出即可。

给定t组测试样例,每组给定长度n,和数组a的每个值

输出需要的执行次数,如果次数大于0,则再按序每行输出执行操作的 下标l 和 r。

题解:

如果只有一个数,则不需要执行任何操作,直接输出1  continue即可

先让头尾相加比较奇偶,让a[1]和a[n]相等,执行了一次。

现在头尾相等了。中间的数不论和头还是和尾相加,都是奇或者都是偶,所以可以分相加和的奇偶情况。来选择和头还是尾相加,最后使中间的数都和头尾相同。

在从第2个数开始,依次和头(因为现在头=尾,所以也是和尾相加比较)相加比较,如果是奇数,则按规定的操作,选择 l 为 1,r 为 i,让a[r] = a[l],使得第i个数和头(也是尾相同)。

如果是偶数,就选择 l 为 i,r 为 n ,按规则,使 a[l] = a[r],使得第i个数和尾(也是头)相同。

头和尾一共有n - 2个数,所以一共执行 n - 2次。

所以一共需要执行 1 + (n - 2) = n - 1次,得到一个每一位数都相等得数组,满足题意.

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n,t,l,r;
int main()
{
	for(cin >> t;t -- ;)
	{
		cin >> n;
		for(int i = 1;i <= n;i ++ )
			cin >> a[i];
		if(n == 1)     //   如果只有一个数,不需要任何操作直接输出即可; 
		{
			cout << "0" << endl;
			continue;
		}
		
		int cot = n - 1; //  定义需要的操作数,如下操作需要 n - 1次; 
		cout << cot << endl;
		cout << 1 << " " << n << endl;   //  先让 A1 + An的值相同,然后从第2个数 至 倒数第2个数 依次和头尾比较 
		if((a[1] + a[n]) % 2 == 0)       //   因为现在头尾的值相同,不管中间的数与头尾相加是奇是偶,都选择能让中间 
			a[1] = a[n];                 //  那个数变成和头尾相同的数,这样就只需要 1(让头尾相同)+ (n-2)(中间依次) 
		else                             //  和头尾相同 =  n - 1次操作,符合题意. 
			a[n] = a[1];
		for(int i = 2;i < n;i ++ )
		{
			if((a[i] + a[1]) % 2 != 0)
			{
				a[i] = a[1];
				cout << 1 << " " << i << endl;
				continue;
			}
			else
			{
				a[i] = a[n];
				cout << i << " " << n << endl;
				continue;	
			}	
		} 
	}
	return 0;
} 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值