目录
- A - Binary Imbalance
- B - Getting Points
- C - Insert and Equalize
A - Binary Imbalance
原题链接
题目描述
给你一个只包含字符0
或1
的字符串 s s s。在每次操作中,你可以从任意两个字符间插入一个字符:如果两个相邻的字符相等,那么你只可以插入1
,否则,你只可以插入0
。是否有可能使用任意数量的运算,使 s s s中0
的个数严格大于1
的个数?
思路:观察
- 只要存在两个相邻的字符不相等,那么可以在中间无限插入
0
,使得其数量大于1
的数量。
public static void solve() throws IOException {int n = readInt();String s = readString();int z = 0, o = 0;if (!s.contains("0")) {printWriter.println("NO");} else {printWriter.println("YES");}
}
B - Getting Points
原题链接
题目描述
一个学期有N
天,为了不被开除,你需要在这N
天内至少拿到P
学分。你每完成一项实践任务,就能获得t
分;每上一堂课,他就能获得l
分,其中实践任务每周一会解锁一个,而课程每天都有。每天,你都可以选择是学习还是休息一整天。当你决定学习时,你可以上一堂课,并完成不超过2
个已解锁但未完成的实践任务。如果你选择休息一整天,那么你将什么也不做。现在你希望休息的天数最大化,问最多可以休息多少天。
思路:二分+分类讨论
- 最大化休息的天数,那么可以理解为最小化学习的天数。
- 二分枚举学习的天数,分类讨论是否可以学完所有实践任务。
- 可以根据
week
的大小进行分类讨论,如果 m i d ≥ w e e k mid \geq week mid≥week,那么可以学完所有实践任务,无论是一天完成一节还是两节实践任务;否则最多只可以学习mid * 2
个学习任务。
def solve():n, s, b, a = map(int, input().split())week = n // 7 + (0 if n % 7 == 0 else 1) # n天内总共有多少周l = 0r = int(1e9) + 10while l + 1 < r:mid = (l + r) >> 1tot = mid * bif mid >= week // 2 + week % 2: # 可以分批次学完所有实践任务tot += week * aelse:tot += mid * 2 * a # mid天内每天学习 2个实践任务if tot >= s:r = midelse:l = midprint(n - r)
C - Insert and Equalize
原题链接
题目描述
给定一个长度为n
且不含重复元素的数组arr
,你需要往数组中插入一个数组中不包含的元素,然后再选择一个数x
,在每次操作中,你可以为数组中的一个数加上x
,求使得数组中所有元素相等的最小操作数。
思路:排序+gcd
- 要使得操作数最小,那么
x
的最优解为排序好的数组的所有相邻元素的差的最大公约数。insert
的值为小于arr[n]
的最大的且不在数组中且与arr[n]的差为gcd
的倍数的值,通过枚举数组可以得到。
public static void solve() throws IOException {int n = readInt();long[] arr = utils.nextLongArray(n);Arrays.sort(arr, 1, n + 1);if (n == 1) {// 数组只有一个元素printWriter.println(1);return;}List<Long> list = new ArrayList<>();for (int i = 2; i <= n; i++) {list.add(arr[i] - arr[i - 1]);// 存下相邻数的差}long gcd = getGcd(0, list);// 获取所有数的 gcdlong insert = Long.MAX_VALUE;// 要插入的元素for (int i = n; i >= 2; i--) {if (arr[i] - arr[i - 1] != gcd) {insert = arr[i] - gcd;break;}}if (insert == Long.MAX_VALUE) {// 无法插入,那么插入一个最小的数 arr[1] - gcdinsert = arr[1] - gcd;}long sum = 0;for (int i = 1; i <= n; i++) {sum += (arr[n] - arr[i]) / gcd;}sum += (arr[n] - insert) / gcd;printWriter.println(sum);
}public static long getGcd(int u, List<Long> list) {if (u == list.size() - 1) {return list.get(u);}long v = getGcd(u + 1, list);return gcd(list.get(u), v);
}public static long gcd(long a, long b) {return b == 0 ? a : gcd(b, a % b);
}