T1 神秘金币

考察大眼观察法,由于 均不相同,而我们又可以每个时刻收集一枚金币,那么我们只需要选出前 大的金币,然后按照 从小到大的顺序收集起来就好了,不会有任何金币消失。

T2 学习乘法

考察乘法的性质

两个数字的和一定,大小越接近,乘积越大。

和一定是因为本题的交换数位只能交换相同的数位,所以交换之后的和是不变的。现在我们考虑如何使得两个数字 尽量接近:

从高位向低位开始看,假设对应位置相同,则继续看下一位,不同,那么我们可以钦定 ,也就是说把大的数字交换到 的当前位,小的数字给 。但是我们又希望两个数字尽量接近,所以我们应该将所有更低位中的大数字交换到数字 上面。最终计算乘积即可。

#include <bits/stdc++.h>
using namespace std;
int main(){
	string s1, s2; // 本题需要对每一个数位进行判断和交换,用字符串显然方便一些
	cin >> s1 >> s2;
	int st = 0;
	for(int i = 0; i < s1.size(); i++){
		if(s1[i] != s2[i]){
			if(s1[i] < s2[i]){
				swap(s1[i], s2[i]); // 钦定 s1 是更大的字符串
			}
			st = i; // 确定第一个不相同数位的位置
			break;
		}
	}
	for(int i = st + 1; i < s1.size(); i++){ // 从 st+1 开始,把剩余位置中的大数字全部给 s2,使得 s1 s2 尽量接近
		if(s1[i] > s2[i]){ 
			swap(s1[i], s2[i]);
		}
	}
	long long ans1 = 0, ans2 = 0;
	for(int i = 0; i < s1.size(); i++){ // 字符串转成数字
		ans1 = ans1 * 10 + s1[i] - '0';
		ans2 = ans2 * 10 + s2[i] - '0';
	}
	cout << ans1 * ans2 << endl;
}

T3 饮料难题

通过大眼观察法可以得知本题的答案是 ,由于数字很大,可以贴一个大整数除法的模板解决本题。

本题的本质是学习除法,在原场景中(10 个饮料瓶,每 3 个瓶子换一瓶饮料,最终能喝 5 瓶饮料)可以看到,10 个饮料瓶最终喝 5 瓶饮料。根据除法的定义:总价除以数量等于单价,得到每瓶饮料的单价是 。得到单价之后,继续根据除法的定义:总价除以单价等于数量,也就是说假设有 元,则可以喝 瓶饮料。

推广到每 个瓶子换一瓶饮料,可以简单发现答案变为

如果还需要证明的话,我们可以根据方程的思想来解决这个问题:

个空瓶子 = 1 瓶饮料 + 1 个空瓶子

两边同时减 1,解得

1 瓶饮料 = 个空瓶子

解方程用到了五到六年级的数学,比较高端,如果可以直接用除法解决当然更好。

T4 手术

  • 题目指出,如果一个患者来了之后发医院里一个优先级低于自己的患者正在理发,他会很痛苦。则表明在区间内不能有优先级高于自己的患者在自己之前理发。因此,当前最高优先级患者应该在最早可理发时刻开始理发,如果往后再理发会导致别的优先级低的患者继续等待。即优先处理优先级高的患者。

  • 初始有一个区间,每次为当前未理发患者其中优先级最高的患者服务,设该患者到达时间是,理发时长是。尽可能找不早于第个单位时间且连续理发时长高于的位置。比方说初始可理发区间集合是。抠掉区间后得到可理发区间集合是。然后当前未理发患者其中优先级最高的患者,则抠掉,然后可理发区间集合变成了。此时暴力复杂度是

  • 分析性质优化复杂度。优先级第高的区间操作后变成了。优先级第高的区间操作后变成了。此时有一个优先级第高的区间,因为塞不下,所以塞到了,变成了被去除的原因是这个区间被优先级第高的访问了但是没有用,所以优先级更低的区间不可能放在里面,因为这个时刻优先级第高的在等待。所以每个位置至多遍历一次,不行的话就没有意义了。使用set维护当前可理发区间,快速定位理发位置。此时暴力复杂度是