Educational Codeforces Round 125 (Rated for Div. 2) A-D

有参考大佬题解,附上链接https://blog.csdn.net/yanweiqi1754989931/article/details/123682475

A

解题思路: 别被题目案例误导,总共只有三种情况
1: x == 0 && y == 0 在原点,不用移动,步数为0。
2: 当sqrt(xx+yy)为整数时,满足题目条件。走欧拉距离,步数为1。
3: 当sqrt(xx+yy)不为整数,走曼哈顿距离,取路线为(0,0)-(x1,0)-(x1,y1)。即一定可以通过0/1/2步且满足题目要求的达到指定地点。
在这里插入图片描述
图中绿色线段即为欧拉距离,红色,蓝色,黄色线段都为等价的曼哈顿距离。题中即取绿色和红色两种路线情况。

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int x, y;
		cin >> x >> y;
		int t = sqrt(x * x + y * y);//用以检验长度是否为整数
		if (x == 0 && y == 0)
			cout << 0 << endl;
		else if (t * t == x * x + y * y)//检验方法
			cout << 1 << endl;
		else
			cout << 2 << endl;
	}
	return 0;
}

B

解题思路: 模拟,因为题目要求不能出现ai>B的情况,因此求每一个元素时应该先加x,再和B比较大小。初始化a=0,当a+x<=B时加用a+x,当a+x>B时,用a-y,用ans记录求和即可。

#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, B, x, y;
		ll ans = 0, a = 0;
		cin >> n >> B >> x >> y;
		for (int i = 1; i <= n; i++)
		{
			if (a + x <= B)
			{
				a += x;
				ans += a;
			}
			else
			{ 
				a -= y;	
				ans += a;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

C

解题思路: 同样是模拟,分为两种情况。注意题目描述:取符合要求的最短的进行删除
1: 当以 ‘(’ 开头时,不管后一个是 ‘(’ 还是 ‘)’ 都满足题目删除条件,可直接进行删除两个字符的操作。
2: 当以 ‘)’ 开头时,只要找到下一个 ‘)’ 便可执行删除中间所有字符的操作(可以举几个例子观察规律)。如果找不到,则说明无法进行删除操作。剩下的字符都是会保留下来的。

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		string str;
		cin >> n >> str;
		int ans = 0;
		while (str.size() > 1)
		{
			if (str[0] == '(')
			{
				str.erase(0,2);//从第一个字符(str[0])开始,删除两个字符
			    ans++;
				continue;
			}
			else
			{
				int po = str.find(')', 1);
				if (po < str.size())
				{
					str.erase(0, po + 1);
					ans++;
				}
				else//返回值大于字符数则说明没找到,停止操作
					break;
			}
		}
		cout << ans << ' ' << str.size() << endl;
	}
	return 0;
}

D

题意理解: Monocarp总共拥有C枚硬币。他可以用这些硬币去招募勇士小队,有n种类型的勇士,输入按顺序给出招募一个所需硬币数,一秒内可以对怪物造成的伤害,第i种类型勇士的生命值。Monocarp共要面对m场战斗,每场中他只能选择一种类型的勇士,且可以在硬币允许的范围下招募同一类型的多个勇士,下面m行依次給出每场战斗怪物每秒造成的伤害和怪物的生命值。题目要求胜任条件是勇士击杀怪物的速度严格快于怪物击杀小队中任何一个勇士的速度
解题思路: 题目要求小队中一个勇士也不会死亡,因此选择一个类型的多个勇士仅等价于将攻击力加倍,生命值不变。(假设招募n个勇士)因此胜利条件为:h/D>H/(dn)——ndh>DH。
1: 输入勇士数据时,求出硬币数一定情况下dh最大值。
2: 对硬币数进行遍历,对于不为0的部分在i
c<C条件下进行翻倍处理,即实现招募多个勇士的情况。在此过程中仍对硬币数一定时做取最大ndh处理。
3: 整理数组,用二分法找出满足题目条件最小的硬币数。

//Monocarp每次只能选择一种类型的勇士,要我方胜利
//因此赢得战斗的条件为(记有n个勇士) h/D>H/(n*d),等于状态也不行
//即获胜条件为:h*n*d>H*D(对于n有:n*c<=C)
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll done[1000005], dsum[1000005];
int main()
{
	ll n, C;
	cin >> n >> C;
	ll c, d, h;
	for (int i = 0; i < n; i++)
	{
		cin >> c >> d >> h;
		done[c] = max(done[c], d * h);
		//在输入每种类型的数据时就记录金币数为c时d*h的最大值
	}
	for (int i = 1; i <= C; i++)//对金币数进行遍历,在<=C的基础上进行翻倍,求出j*d*h
		if(done[i])//当金币数对应的值为0时无需处理
		    for (int j = 1; i * j <= C; j++)
				dsum[i * j] = max(dsum[i * j], done[i] * j);
	//此时处理完后的dsum数组中间断存在很多0项,遍历dsum数组,用前面大的值覆盖后面金币数多但值反而小的部分
	//使序列具有从小到大的顺序,便于后面用二分处理找到第一个大于怪物生命值的位置
	//不能去掉0或者直接排序,会影响数值与金币数的对应关系
	for (int i = 1; i <= C; i++)
		dsum[i] = max(dsum[i - 1], dsum[i]);
	ll m;
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		ll D, H;
		cin >> D >> H;
		ll l = 0, r = C + 1 , ans = -1;//r=C情况下会导致最大点C遍历不到出现错误
		while (l < r)
		{
			ll mid = l + r >> 1;
			if (dsum[mid] > D * H)
			{
				r = mid;
				ans = mid;
			}
			else
				l = mid + 1;
		}
		cout << ans << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值