Educational Codeforces Round 135 (Rated for Div. 2)

题目链接

A

题意:

一个包里有 n 种颜色的球一共有奇数个,已知每一种球的数量,每次可以选择2个不同颜色的球,求最后可能剩下的球的颜色,任意输出一组解。

核心思路:不需要想太多,根据题目需要模拟就好了。

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
int inf = 1 << 31 - 1;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5 + 10;
int a[N];
void solve()
{
	int n;
	cin >> n;
	int max = -inf;
	int ans = 0;
	for (int i = 1;i <= n;i++)
	{
		cin >> a[i];
		if (a[i] >= max)
		{
			max = a[i];
			ans = i;
		}
	}
	cout << ans<< endl;
}
int main()
{
	IOS;
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}	

B

题意:

定义一个排序的价值value为:初始有一个x,从第一个元素p1开始,如果x < p1,x += p1,else x = 0,如此循环,最终x的值为该排列的总价值。请构造一个排列使得该价值最大。

核心思路:我们需要注意1 2 3 4,这正序排列的是不可取的,因为这样子下去会是0.然后我们发现我们要是价值最大化,所以就需要前两个数相加是需要小于第三个数的,那样x才不会被清0.但是我们会发现这样的我们需要找一些间隔比较大的才可以满足要求。所以我们需要从题目出发,我们会发现样例给的几个答案都是n+n-1,所以我们可以大胆猜测其实这个但是就是这个值。接下来就想着怎么围绕这个值去进行构造。很显然分他们的长度为奇偶讨论就好了.

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
int inf = 1 << 31 - 1;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5 + 10;
int a[N];
void solve()
{
	int n;
	cin >> n;
	if (n % 2==0)
	{
		for (int i = n - 2;i >= 1;i--)
			cout << i << " ";
		cout << n - 1 << " " << n << endl;
	}
	else
	{
		for (int i = n - 2;i >= 4;i--)
		{
			cout << i << " ";
		}
		cout << 1 << " " << 2 << " " << 3 << " " << n - 1 << " " << n << endl;
	}
}
int main()
{
	IOS;
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}	

C

题意:

给定两个数组a和b,每次进行一次操作可以使其中一个数组中的一个数变成其十进制的位数。求使得在不考虑顺序的情况下,a和b数组相等的最少操作数。

核心思路:其实这个是很简单的,我们只需要先排序在一个一个排查记好了,排序的话直接放入大根堆就好了。有个需要注意的是这个lg操作和我们传统的是不一样的。我们可以理解为就是求字符串的长度。

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
int inf = 1 << 31 - 1;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5 + 10;
int a[N];
int f(int x)
{
	return to_string(x).length();
}
void solve()
{
	string s;
	cin >> s;
	int flag = 0;
	for (int i = 0;i < s.size() / 2 + 1;i++)
	{
		if (s[i] != s[s.size() - i - 1])
		{
			for (int j = i;j < s.size() - i - 1;j++)//其实也只是循环了一边主串
			{
				if (s[j] != s[j + 1])
				{
					flag = 1;
				}
			}
			break;
		}
	}
	if (flag)
		cout << "Alice" << endl;
	else
		cout << "Draw" << endl;
}
int main()
{
	IOS;
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}	

D

题意:

给定一个字符串,两人每次可以从头和尾拿走一个字符,拿走的字符放到字符串的开头,字典序小的人获胜,求最终谁赢或者平手。

核心思路:这明显是个博弈论的题目。所以我们需要想什么是必输局面,什么是平局,什么是必赢局面在先手的情况下。其实我们通过模拟几个发现:先手是就只有两种局面,一种是必赢另外一种是平局。因为我们第一步总是可以采取最优策略是对手陷入必输或者平局的状态。举一个例子说明下,先这种极端的例子:

b a b b 
Alice:b a
Bob:b b

所以我们只需要考虑平局状态:这个就比较好处理了。例子:aabb,就是我们可以使用指针判断前一个和后一个是否相等就好了。

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
int inf = 1 << 31 - 1;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5 + 10;
int a[N];
int f(int x)
{
	return to_string(x).length();
}
void solve()
{
	string s;
	cin >> s;
	int flag = 0;
	for (int i = 0;i < s.size() / 2 + 1;i++)
	{
		if (s[i] != s[s.size() - i - 1])//不等于就循环一遍,等于就直接跳过了.
		{
			for (int j = i;j < s.size() - i - 1;j+=2)//其实也只是循环了一边主串
			{
				if (s[j] != s[j + 1])
				{
					flag = 1;
				}
			}
			break;
		}
	}
	if (flag)
		cout << "Alice" << endl;
	else
		cout << "Draw" << endl;
}
int main()
{
	IOS;
	int T;
	cin >> T;
	while (T--)
	{
		solve();
	}
}	

E题好像是一些数学知识,可以补。

posted @ 2022-12-09 17:56  努力的德华  阅读(21)  评论(0)    收藏  举报