Codeforces Round 957 (Div. 3)

A. Only Pluses

题目:

Kmes has written three integers a a a, b b b and c c c in order to remember that he has to give Noobish_Monk a × b × c a \times b \times c a×b×c bananas.

Noobish_Monk has found these integers and decided to do the following at most 5 5 5 times:

  • pick one of these integers;
  • increase it by 1 1 1.
    For example, if a = 2 a = 2 a=2, b = 3 b = 3 b=3 and c = 4 c = 4 c=4, then one can increase a a a three times by one and increase b b b two times. After that a = 5 a = 5 a=5, b = 5 b = 5 b=5, c = 4 c = 4 c=4. Then the total number of bananas will be 5 × 5 × 4 = 100 5 \times 5 \times 4 = 100 5×5×4=100.

What is the maximum value of a × b × c a \times b \times c a×b×c Noobish_Monk can achieve with these operations?

题意:

Kmes 写了三个整数 a a a b b b c c c ,以便记住他必须给 Noobish_Monk a × b × c a \times b \times c a×b×c 香蕉。

Noobish_Monk 找到了这些整数,并决定最多进行 5 5 5 次下列操作:

  • 从这些整数中选择一个
  • 将它增加 1 1 1

例如,如果是 a = 2 a = 2 a=2 b = 3 b = 3 b=3 c = 4 c = 4 c=4 ,那么可以将 a a a 增加三次,再将 b b b 增加两次。之后是 a = 5 a = 5 a=5 b = 5 b = 5 b=5 c = 4 c = 4 c=4 。那么香蕉的总数就是 5 × 5 × 4 = 100 5 \times 5 \times 4 = 100 5×5×4=100

Noobish_Monk 通过这些运算可以得到的最大值 a × b × c a \times b \times c a×b×c 是多少?

分析:

给定三个数字,任意对这三个数字进行5次加一操作,找到操作后三个数乘积的最大值。想要找到乘积最大值,我们要使这三个数尽可能都较大,故我们对这三个数进行排序,每次对最小值进行操作,重新排序,循环操作5次,即可得到乘积最大值。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e8+10;

int main()
{
	int tt;
	cin >> tt;
	while(tt--)
	{
		int a[3],n=3;
		for(int i=1;i<=3;i++)
		{
			cin >> a[i];
		}
		for(int i=1;i<=5;i++)
		{
			sort(a+1,a+n+1);
			a[1]++;
		}
		cout << a[1]*a[2]*a[3] << endl;
	}
	return 0;
 } 

B. Angry Monk

题目:

To celebrate his recovery, k1o0n has baked an enormous n n n metres long potato casserole.

Turns out, Noobish_Monk just can’t stand potatoes, so he decided to ruin k1o0n’s meal. He has cut it into k k k pieces, of lengths a 1 , a 2 , … , a k a_1, a_2, \dots, a_k a1,a2,,ak meters.

k1o0n wasn’t keen on that. Luckily, everything can be fixed. In order to do that, k1o0n can do one of the following operations:

  • Pick a piece with length a i ≥ 2 a_i \ge 2 ai2 and divide it into two pieces with lengths 1 1 1 and a i − 1 a_i - 1 ai1. As a result, the number of pieces will increase by 1 1 1;
  • Pick a slice a i a_i ai and another slice with length a j = 1 a_j=1 aj=1 ( i ≠ j i \ne j i=j) and merge them into one piece with length a i + 1 a_i+1 ai+1. As a result, the number of pieces will decrease by 1 1 1.

Help k1o0n to find the minimum number of operations he needs to do in order to merge the casserole into one piece with length n n n.

For example, if n = 5 n=5 n=5, k = 2 k=2 k=2 and a = [ 3 , 2 ] a = [3, 2] a=[3,2], it is optimal to do the following:

  1. Divide the piece with length 2 2 2 into two pieces with lengths 2 − 1 = 1 2-1=1 21=1 and 1 1 1, as a result a = [ 3 , 1 , 1 ] a = [3, 1, 1] a=[3,1,1].
  2. Merge the piece with length 3 3 3 and the piece with length 1 1 1, as a result a = [ 4 , 1 ] a = [4, 1] a=[4,1].
  3. Merge the piece with length 4 4 4 and the piece with length 1 1 1, as a result a = [ 5 ] a = [5] a=[5].

题意:

为了庆祝他的康复,k1o0n 烤了一个长达 n n n 米的巨大马铃薯砂锅。

原来,Noobish_Monk 就是受不了土豆,所以他决定毁了 k1o0n 的大餐。他把土豆切成了 k k k 块,长度为 a 1 , a 2 , … , a k a_1, a_2, \dots, a_k a1,a2,,ak 米。

k1o0n 并不喜欢这样。幸运的是,一切都可以补救。为此,k1o0n 可以执行以下操作之一:

  • 选取长度为 a i ≥ 2 a_i \ge 2 ai2 的棋子,将其分成长度为 1 1 1 a i − 1 a_i - 1 ai1 的两个棋子。这样,棋子的数量将增加 1 1 1
  • 选取一个长度为 a i a_i ai 的片段和另一个长度为 a j = 1 a_j=1 aj=1 i ≠ j i \ne j i=j )的片段,将它们合并为一个长度为 a i + 1 a_i+1 ai+1 的片段。这样,棋子的数量将减少 1 1 1

帮助 k1o0n 求出将砂锅合并成长度为 n n n 的一块所需的最少操作数。

例如,如果 n = 5 n=5 n=5 k = 2 k=2 k=2 a = [ 3 , 2 ] a = [3, 2] a=[3,2] ,最佳操作如下:

  1. 将长度为 2 2 2 的棋子分成长度为 2 − 1 = 1 2-1=1 21=1 1 1 1 的两块,结果为 a = [ 3 , 1 , 1 ] a = [3, 1, 1] a=[3,1,1]
  2. 合并长度为 3 3 3 的棋子和长度为 1 1 1 的棋子,得到 a = [ 4 , 1 ] a = [4, 1] a=[4,1]
  3. 将长度为 4 4 4 的棋子与长度为 1 1 1 的棋子合并,得到 a = [ 5 ] a = [5] a=[5]

分析:

要用最少的操作实现数组的合并,我们要保留数组的最大元素,对其他各元素均进行操作使其分为一定量的元素1,再将所有的元素1与最大元素一一合并。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll n,k,a[N];
int main()
{
	int tt;
	cin >> tt;
	while(tt--)
	{
		cin >> n >> k;
		for(int i=1;i<=k;i++) 
			cin >> a[i];
		sort(a+1,a+k+1);
		ll ans=0;
		for(int i=1;i<k;i++)
			ans+=2*a[i]-1; //对该元素的总操作数
		cout << ans << endl;
	}
	return 0;
 } 

C. Gorilla and Permutation

题目:

Gorilla and Noobish_Monk found three numbers n n n, m m m, and k k k ( m < k m < k m<k). They decided to construct a permutation † ^{\dagger} of length n n n.

For the permutation, Noobish_Monk came up with the following function: g ( i ) g(i) g(i) is the sum of all the numbers in the permutation on a prefix of length i i i that are not greater than m m m. Similarly, Gorilla came up with the function f f f, where f ( i ) f(i) f(i) is the sum of all the numbers in the permutation on a prefix of length i i i that are not less than k k k. A prefix of length i i i is a subarray consisting of the first i i i elements of the original array.

For example, if n = 5 n = 5 n=5, m = 2 m = 2 m=2, k = 5 k = 5 k=5, and the permutation is [ 5 , 3 , 4 , 1 , 2 ] [5, 3, 4, 1, 2] [5,3,4,1,2], then:

  • f ( 1 ) = 5 f(1) = 5 f(1)=5, because 5 ≥ 5 5 \ge 5 55; g ( 1 ) = 0 g(1) = 0 g(1)=0, because 5 > 2 5 > 2 5>2;
  • f ( 2 ) = 5 f(2) = 5 f(2)=5, because 3 < 5 3 < 5 3<5; g ( 2 ) = 0 g(2) = 0 g(2)=0, because 3 > 2 3 > 2 3>2;
  • f ( 3 ) = 5 f(3) = 5 f(3)=5, because 4 < 5 4 < 5 4<5; g ( 3 ) = 0 g(3) = 0 g(3)=0, because 4 > 2 4 > 2 4>2;
  • f ( 4 ) = 5 f(4) = 5 f(4)=5, because 1 < 5 1 < 5 1<5; g ( 4 ) = 1 g(4) = 1 g(4)=1, because 1 ≤ 2 1 \le 2 12;
  • f ( 5 ) = 5 f(5) = 5 f(5)=5, because 2 < 5 2 < 5 2<5; g ( 5 ) = 1 + 2 = 3 g(5) = 1 + 2 = 3 g(5)=1+2=3, because 2 ≤ 2 2 \le 2 22.

Help them find a permutation for which the value of ( ∑ i = 1 n f ( i ) − ∑ i = 1 n g ( i ) ) \left(\sum_{i=1}^n f(i) - \sum_{i=1}^n g(i)\right) (i=1nf(i)i=1ng(i)) is maximized.

† ^{\dagger} A permutation of length n n n is an array consisting of n n n distinct integers from 1 1 1 to n n n in any order. For example, [ 2 , 3 , 1 , 5 , 4 ] [2,3,1,5,4] [2,3,1,5,4] is a permutation, but [ 1 , 2 , 2 ] [1,2,2] [1,2,2] is not a permutation (as 2 2 2 appears twice in the array) and [ 1 , 3 , 4 ] [1,3,4] [1,3,4] is also not a permutation (as n = 3 n=3 n=3, but 4 4 4 appears in the array).

题意:

Gorilla 和 Noobish_Monk 发现了三个数字 n 、 m和 k( m<k )。他们决定构造一个长度为 n的排列组合 †。
对于这个排列,Noobish/Monk 想到了下面的函数: g(i)是长度为 i的前缀上的排列中所有不大于 m的数字之和。同样,Gorilla 提出了函数 f,其中 f(i)是长度为 i的前缀上不小于 k的排列中所有数字之和。长度为 i的前缀是由原始数组的前 i 个元素组成的子数组。

例如,如果 n = 5 n = 5 n=5, m = 2 m = 2 m=2, k = 5 k = 5 k=5,且排列为 [ 5 , 3 , 4 , 1 , 2 ] [5,3,4,1,2] [5,3,4,1,2],那么:

  • f ( 1 ) = 5 f(1) = 5 f(1)=5, because 5 ≥ 5 5 \ge 5 55; g ( 1 ) = 0 g(1) = 0 g(1)=0, because 5 > 2 5 > 2 5>2;
  • f ( 2 ) = 5 f(2) = 5 f(2)=5, because 3 < 5 3 < 5 3<5; g ( 2 ) = 0 g(2) = 0 g(2)=0, because 3 > 2 3 > 2 3>2;
  • f ( 3 ) = 5 f(3) = 5 f(3)=5, because 4 < 5 4 < 5 4<5; g ( 3 ) = 0 g(3) = 0 g(3)=0, because 4 > 2 4 > 2 4>2;
  • f ( 4 ) = 5 f(4) = 5 f(4)=5, because 1 < 5 1 < 5 1<5; g ( 4 ) = 1 g(4) = 1 g(4)=1, because 1 ≤ 2 1 \le 2 12;
  • f ( 5 ) = 5 f(5) = 5 f(5)=5, because 2 < 5 2 < 5 2<5; g ( 5 ) = 1 + 2 = 3 g(5) = 1 + 2 = 3 g(5)=1+2=3, because 2 ≤ 2 2 \le 2 22.
    帮助他们找出一个使 ( ∑ i = 1 n f ( i ) − ∑ i = 1 n g ( i ) ) \left(\sum_{i=1}^n f(i) - \sum_{i=1}^n g(i)\right) (i=1nf(i)i=1ng(i))的值最大的排列。

{长度为 n的排列是由 n个不同的整数组成的数组,这些整数从 1 到 n ,顺序不限。例如, [2,3,1,5,4] 是一个排列,但 [1,2,2]不是排列(因为 2 在数组中出现了两次), [1,3,4] 也不是排列(因为 n=3,但 4在数组中出现)。

分析:

我们需要构造一个长度为n的排列,要使得 ( ∑ i = 1 n f ( i ) − ∑ i = 1 n g ( i ) ) \left(\sum_{i=1}^n f(i) - \sum_{i=1}^n g(i)\right) (i=1nf(i)i=1ng(i))结果尽可能大,我们需要将大于等于k的元素按降序放在排列最前面,将小于等于m的元素按升序放在排列最后面,其余元素任意排列。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll n,m,k,a[N];
int main()
{
	int tt;
	cin >> tt;
	while(tt--)
	{
		cin >> n >> m >> k;
		ll x=n,y=1;
		for(int i=1;i<=n-m;i++)
		{
			a[i]=x--;
		}
		for(int i=n-m+1;i<=n;i++)
		{
			a[i]=y++;
		}
		for(int i=1;i<=n;i++)
		{
			cout << a[i] << ' ';
		}
		cout << endl;
	}
	return 0;
 } 

D. Test of Love

题目:

ErnKor is ready to do anything for Julen, even to swim through crocodile-infested swamps. We decided to test this love. ErnKor will have to swim across a river with a width of 1 1 1 meter and a length of n n n meters.

The river is very cold. Therefore, in total (that is, throughout the entire swim from 0 0 0 to n + 1 n+1 n+1) ErnKor can swim in the water for no more than k k k meters. For the sake of humanity, we have added not only crocodiles to the river, but also logs on which he can jump. Our test is as follows:

Initially, ErnKor is on the left bank and needs to reach the right bank. They are located at the 0 0 0 and n + 1 n+1 n+1 meters respectively. The river can be represented as n n n segments, each with a length of 1 1 1 meter. Each segment contains either a log ‘L’, a crocodile ‘C’, or just water ‘W’. ErnKor can move as follows:

  • If he is on the surface (i.e., on the bank or on a log), he can jump forward for no more than m m m ( 1 ≤ m ≤ 10 1 \le m \le 10 1m10) meters (he can jump on the bank, on a log, or in the water).
  • If he is in the water, he can only swim to the next river segment (or to the bank if he is at the n n n-th meter).
  • ErnKor cannot land in a segment with a crocodile in any way.

Determine if ErnKor can reach the right bank.

题意:

恩科尔愿意为朱伦做任何事,甚至愿意游过鳄鱼出没的沼泽。我们决定测试一下这份爱。恩科尔必须游过一条宽 1 1 1 米、长 n n n 米的河流。

河水非常冷。因此,***(即从 0 0 0 游到 n + 1 n+1 n+1 的整个过程)恩科尔在水中游泳的总长度不超过 k k k 米。为了人性化起见,我们不仅在河里加入了鳄鱼,还加入了可以让他跳上去的圆木。我们的测试如下

一开始,恩科尔在左岸,需要到达右岸。它们分别位于 0 0 0 n + 1 n+1 n+1 米处。河流可以表示为 n n n 个河段,每个河段的长度为 1 1 1 米。每个河段都包含原木 “L”、鳄鱼 "C "或水 “W”。恩科的移动方式如下

  • 如果他在水面上(即岸上或圆木上),他可以向前跳跃不超过 m m m ( 1 ≤ m ≤ 10 1 \le m \le 10 1m10 ) 米(他可以在岸上、圆木上或水中跳跃)。
  • 如果他在水中,他只能游到下一个河段(如果他在 n n n n n n )米处,则只能游到岸边)。
  • 无论如何,ErnKor 都不能在有鳄鱼的河段登陆。

确定恩科是否能到达右岸。

分析:

要判断ErnKor 是否能到达对面,我们只需对两个地方进行判断:
第一,ErnKor 是否能跳过所有的鳄鱼,即判断从原木(岸边)到鳄鱼的距离是否大于ErnKor 的跳跃距离,若无法跳过,则不能到达对岸。
第二,ErnKor 游过的距离是否超过其最大游泳距离,当跳跃距离不足必须游泳才能前进前进时,记录游泳的距离,判断游泳距离是否大于最大游泳距离,若大于,则ErnKor 无法到达河对岸。
若以上两条均满足题意,则ErnKor 可以到达河对岸。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2*1e5+10;
ll n,m,k;
char a[N];

void fun()
{
	int water=0,ans=0,ans1=0;
	cin >> a;
	for(int i=0;a[i]!='\0';i++)
	{
		if(a[i]=='L') {
			ans1=0;
		}
		else {
			ans=max(ans,++ans1);
			if(ans1>=m&&a[i]=='C'){ //判断是否能跳过鳄鱼
				cout << "NO" << endl;
				return;
			}
			else if(ans1>=m&&a[i]=='W') //计算游泳距离
			water++;
			if(water>k){
			cout << "NO" << endl;
			return;
			}	
		}
	}
	cout << "YES" << endl;
}
int main()
{
	int tt;
	cin >> tt;
	while(tt--)
	{
		cin >> n >> m >> k;
		fun();
	}
	return 0;
 } 

E. Novice’s Mistake

题目:

One of the first programming problems by K1o0n looked like this: “Noobish_Monk has n n n ( 1 ≤ n ≤ 100 ) (1 \le n \le 100) (1n100) friends. Each of them gave him a a a ( 1 ≤ a ≤ 10000 ) (1 \le a \le 10000) (1a10000) apples for his birthday. Delighted with such a gift, Noobish_Monk returned b b b ( 1 ≤ b ≤ min ⁡ ( 10000 , a ⋅ n ) ) (1 \le b \le \min(10000, a \cdot n)) (1bmin(10000,an)) apples to his friends. How many apples are left with Noobish_Monk?”

K1o0n wrote a solution, but accidentally considered the value of n n n as a string, so the value of n ⋅ a − b n \cdot a - b nab was calculated differently. Specifically:

  • when multiplying the string n n n by the integer a a a, he will get the string s = n + n + ⋯ + n + n ⏟ a  times s=\underbrace{n + n + \dots + n + n}_{a\ \text{times}} s=a times n+n++n+n
  • when subtracting the integer b b b from the string s s s, the last b b b characters will be removed from it. If b b b is greater than or equal to the length of the string s s s, it will become empty.

Learning about this, ErnKor became interested in how many pairs ( a , b ) (a, b) (a,b) exist for a given n n n, satisfying the constraints of the problem, on which K1o0n’s solution gives the correct answer.

“The solution gives the correct answer” means that it outputs a non-empty string, and this string, when converted to an integer, equals the correct answer, i.e., the value of n ⋅ a − b n \cdot a - b nab.

题意:

K1o0n 的第一个编程问题是这样的"Noobish_Monk有 n n n 个朋友。 ( 1 ≤ n ≤ 100 ) (1 \le n \le 100) (1n100) 个朋友。每个朋友都送给他 a a a ( 1 ≤ a ≤ 10000 ) (1 \le a \le 10000) (1a10000) 个苹果。 ( 1 ≤ a ≤ 10000 ) (1 \le a \le 10000) (1a10000) 个苹果作为生日礼物。收到这样的礼物后,诺比希/蒙克很高兴,他回赠了 b b b 个苹果。 ( 1 ≤ b ≤ min ⁡ ( 10000 , a ⋅ n ) ) (1 \le b \le \min(10000, a \cdot n)) (1bmin(10000,an)) 个苹果给他的朋友们。诺比西和尚还剩下多少个苹果?"

K1o0n 写了一个解决方案,但不小心把 n n n 的值看成了字符串,所以 n ⋅ a − b n \cdot a - b nab 的值的计算方法不同。具体来说

  • 将字符串 n n n 乘以整数 a a a ,得到字符串 s = n + n + ⋯ + n + n ⏟ a  times s=\underbrace{n + n + \dots + n + n}_{a\ \text{times}} s=a times n+n++n+n
  • 从字符串 s s s 中减去整数 b b b 时,将删除最后的 b b b 个字符。如果 b b b 大于或等于字符串 s s s 的长度,则字符串 b b b 将变为空。

了解到这一点后,ErnKor 开始关注在给定的 n n n 中,有多少对 ( a , b ) (a, b) (a,b) 可以满足问题的约束条件,而 K1o0n 的解给出了正确答案。

"解法给出了正确答案 "意味着它输出了一个非空字符串,这个字符串转换成整数后等于正确答案,即 n ⋅ a − b n \cdot a - b nab 的值。

分析:

例n=10时,设num为n的位数,此时num=2,我们可以得到以下等式:
numa-b=1,na-b=1;
numa-b=2,na-b=10;
numa-b=3,na-b=101;
numa-b=4,na-b=1010;
numa-b=5,na-b=10101;

根据题意 a和b的值均小于10000,故最多有5个等式满足条件,求解上述等式,得到正整数a,b,再判断是否符合题中所给范围,即可求解。

代码实现:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int n,t[10],num=0;
 
void fun()
{
	int ans=0,temp=0;
	int x[N],y[N],t[10];
	int n1=n;
		while(n1){
			n1/=10;
			num++;
		}
		if(num==3){
			t[1]=t[4]=n/100;
			t[2]=t[5]=(n/10)-t[1]*10;
			t[3]=n%10;
		}
		else if(num==2){
			t[1]=t[3]=t[5]=n/10;
			t[2]=t[4]=n%10; 
		}
		else{
			t[1]=t[2]=t[3]=t[4]=t[5]=n;
		}
	for(int i=1,j=1;i<=5;i++)
	{
		temp=temp*10+t[i];
		int p=temp-i,q=n-num;
		if(p%q==0){//判断是否为整数
			x[j]=(temp-i)/(n-num);
		    y[j]=x[j]*num-i;	
			if(x[j]>=1&&x[j]<=10000&&y[j]>=1&&y[j]<=min(10000,x[j]*n)){
				ans++;
				j++;
		    }
		}
		else
		continue;
	}
	cout << ans << endl;
	for(int i=1;i<=ans;i++)
	{
		cout << x[i] << ' ' << y[i] << endl;
	}
}
int main()
{
	int tt;
	cin >> tt;
	while(tt--)
	{
		num=0;
		cin >> n;
		if(n==1) //1比较特殊,单独输出
		{
			int ans=9999;
			cout << ans << endl;
			for(int i=1;i<=9999;i++)
			{
				cout << i+1 << ' ' << i << endl;
			}
		}
		else
		fun();
	}
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值