题目发布于2021年10月11日零点。
Problem A
题目描述
我们有\(n\)根的木棍。现在从这些木棍中切割出来\(m\)条长度相同的木棍,问这\(m\)根木棍最长有多长?
题解
实际上就是切绳子的问题,直接贴代码。注意\(r\)要足够大,\(l\)最好不要取负数
1 |
|
Problem B
题目描述
有一条河,河中间有一些石头,已知石头的数量和相邻两块石头之间的距离。现在可以移除一些石头,问最多移除\(m\)块石头后(首尾两块石头不可以移除),相邻两块石头之间的距离的最小值最大是多少。
输入数据
第一行输入两个数字,\(n(2 \leq n \leq 1000)\)为石头的个数,\(m(0 \leq m \leq n-2)\)为可移除的石头数目,随后\(n-1\)个数字,表示顺序和相邻两块石头的距离\(d(d \leq 1000)\)。
题解
这个题乍看很迷惑,事实上这个题可以用二分查找进行解决。逆向思考,判断任意两块石头之间的距离均大于等于\(d\)时,移除石头数\(f(d)\)是否满足\(f(d) \leq m\)。直接使用 vector
可以避免用 list
删除时的各种麻烦。
1 |
|
Problem C
题目描述
楼梯有n阶,可以一步上一阶、两阶或三阶,问有多少种不同的走法。由于答案很大,模\(10^9+7\)输出。
题解
动态规划可解的题目,比较基础。
1 |
|
Problem D
题目描述
一个快递公司要将\(n\)个包裹分别送到\(n\)个地方,并分配给邮递员小K一个事先设定好的路线,小K需要开车按照路线给的地点顺序相继送达,且不能遗漏一个地点。小K得到每个地方可以签收的时间段,并且也知道路线中一个地方到下一个地方的距离。若到达某一个地方的时间早于可以签收的时间段,则必须在这个地方停留至可以签收,但不能晚于签收的时间段,可以认为签收的过程是瞬间完成的。 为了节省燃料,小K希望在全部送达的情况下,车的最大速度越小越好,就找到了你给他设计一种方案,并求出车的最大速度最小是多少。
输入数据
第1行为一个正整数\(n(n<2×10^4)\),表示需要运送包裹的地点数。
下面 n 行,第 i+1 行有 3 个正整数\(x_i,y_i,s_i\), 表示按路线顺序给出第\(i\)个地点签收包裹的时间段为\([x_i,y_i]\),即最早为距出发时刻\(x_i\),最晚为距出发时刻\(y_i\),从前一个地点到达第\(i\)个地点距离为 \(s_i\),且保证路线中\(x_i\)递增。
可以认为\(s1\)为出发的地方到第\(1\)个地点的距离,且出发时刻为\(0\)。
题解
还是二分查找的题目。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using namespace std;
const double eps = 0.00001;
bool valid(vector<int>& x, vector<int>& y, vector<int>& s, long double mid);
int main() {
int n;
cin >> n;
vector<int> x(n), y(n), s(n);
long double ans = 0.0;
for (int i = 0; i < n; i++) {
cin >> x[i] >> y[i] >> s[i];
}
long double l = 1, r = 1e9;
while (r -l >= eps) {
long double mid = (l + r) / 2;
if (valid(x, y, s, mid)) {
ans = mid;
r = mid;
}
else {
l = mid;
}
}
cout << fixed << setprecision(2);
cout << ans << endl;
return 0;
}
bool valid(vector<int>& x, vector<int>& y, vector<int>& s, long double mid) {
int n = x.size();
long double t = 0.0;
for (int i = 0; i < n; i++) {
t += s[i] / mid;
t = (t < x[i] ? x[i] : t);
if (t > y[i]) {
return false;
}
}
return true;
}
Problem E
题目描述
有ABC三根杆和一些圆盘,开始的时候圆盘从小到大摞在A杆上,小盘在上大盘在下,规定如果圆盘p摞在圆盘q上面,那么\(r_p \leq r_q\),\(r_p\)和\(r_q\)为p和q的半径。 现在有若干个圆盘,半径从\(1\)到\(n\),半径为\(i\)的圆盘有\(i\)个,每次操作可以移动一个圆盘,问把所有圆盘从A杆移动到C杆上最少需要几次操作。 由于最终答案可能很大,所以答案对\(10^9+7\)取模输出。
题解
汉诺塔升级版,对于汉诺塔而言,初始状态A柱上从上往下数第\(i\)个盘子共需要被移动\(2^{n-i}\)次;对于该问题而言,初始状态A柱上从上往下数第\(i\)个盘子共需要被移动\(i * 2^{n-i}\)次,用快速幂求解就行。
值得注意的是,快速幂中 x
要取 long long
才够用。
1 |
|