P10909 [蓝桥杯 2024 国 B] 立定跳远(二分)
https://www.luogu.com.cn/problem/P10909
题目描述
在运动会上,小明从数轴的原点开始向正方向立定跳远。项目设置了 n n n 个检查点 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots , a_n a1,a2,⋯,an 且 a i ≥ a i − 1 > 0 a_i \ge a_{i−1} > 0 ai≥ai−1>0。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时,小明可以自行再增加 m m m 个检查点让自己跳得更轻松。
在运动会前,小明制定训练计划让自己单次跳跃的最远距离达到 L L L,并且学会一个爆发技能可以在运动会时使用一次,使用时可以在该次跳跃时的最远距离变为 2 L 2L 2L。小明想知道, L L L 的最小值是多少可以完成这个项目?
输入格式
输入共 2 2 2 行。
第一行为两个正整数 n , m n,m n,m。
第二行为 n n n 个由空格分开的正整数 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an。
输出格式
输出共 1 1 1 行,一个整数表示答案。
输入输出样例 #1
输入 #1
5 3
1 3 5 16 21
输出 #1
3
说明/提示
【样例说明】
增加检查点 10 , 13 , 19 10, 13, 19 10,13,19,因此每次跳跃距离为 1 , 2 , 2 , 5 , 3 , 3 , 3 , 2 1,2, 2, 5, 3, 3, 3, 2 1,2,2,5,3,3,3,2,在第三次跳跃时使用技能即可。
【评测用例规模与约定】
对于
20
%
20\%
20% 的评测用例,保证
n
≤
1
0
2
n \le 10^2
n≤102,
m
≤
1
0
3
m \le 10^3
m≤103,
a
i
≤
1
0
3
a_i \le 10^3
ai≤103。
对于
100
%
100\%
100% 的评测用例,保证
2
≤
n
≤
1
0
5
2 \le n \le 10^5
2≤n≤105,
m
≤
1
0
8
m \le 10^8
m≤108,
0
<
a
i
≤
1
0
8
0 < a_i \le 10^8
0<ai≤108。
解题思路
考虑如何判断一个跳跃距离 L L L(不要求最小)是否可以完成这个项目
我们设第 n − 1 n-1 n−1 个检查点与第 n n n 个检查点之间的距离为 s n s_n sn,若:
- s n ≤ L s_n \leq L sn≤L,则小明可以直接从第 n − 1 n-1 n−1 个检查点跳到第 n n n 个检查点;
- s n > L s_n > L sn>L 且 s n ≤ ( t + 1 ) L s_n \leq (t+1)L sn≤(t+1)L,则小明需要增加 t t t 个额外检查点,以从第 n − 1 n-1 n−1 个检查点跳到第 n n n 个检查点。
可用的额外检查点有多少个? m + 1 m+1 m+1 个。因为,使用一次“爆发技能”其实和一个额外检查点的效果等同。
将指定 L L L 需要的额外检查点数目累加。如果该数目小于 m + 1 m+1 m+1,则可以认为该 L L L 是可以完成这个项目的。
以上过程的时间复杂度为 O ( n ) O(n) O(n)。
考虑如何找出符合条件的最小 L L L 值
注意到若设可以完成这个项目的最小 L L L 值为 L min L_{\min} Lmin,则当 L > L min L > L_{\min} L>Lmin 时,也一定可以完成这个项目;当 L < L min L < L_{\min} L<Lmin 时,一定不可以完成这个项目。
我们可以用二分查找的方式找到那个最小的 L L L。
假设我们已知 L min L_{\min} Lmin 的范围为 l ≤ L min ≤ r l \leq L_{\min} \leq r l≤Lmin≤r。令 m i d = l + r 2 mid = \frac{l + r}{2} mid=2l+r,若:
- L = m i d L = mid L=mid 时可以完成这个项目。此时 L min L_{\min} Lmin 的范围缩小至 l ≤ L min ≤ m i d l \leq L_{\min} \leq mid l≤Lmin≤mid;
- L = m i d L = mid L=mid 时不可以完成这个项目。此时 L min L_{\min} Lmin 的范围缩小至 m i d + 1 ≤ L min ≤ r mid + 1 \leq L_{\min} \leq r mid+1≤Lmin≤r。
当范围最终缩小到一个确定的数时,此时 l l l 或 r r r 的值即为 L min L_{\min} Lmin 的值。
AC Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+9;
int a[N], n, m;
bool check(int x) {
int cnt = 0;
for (int i = 1; i <= n; i++) {
int dis = a[i] - a[i - 1];
if (dis <= x){
continue;
}
cnt += (int)ceil(1.0 * dis / x) - 1;
if (cnt > m) {
return false;
}
}
return true;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
m++;
int l = 1, r = a[n], res = -1;
while(l <= r) {
int mid = (l + r) >> 1;
if (check(mid)){
r = mid - 1, res = mid;
}
else {
l = mid + 1;
}
}
cout << res;
return 0;
}
P10424 [蓝桥杯 2024 省 B] 好数
https://www.luogu.com.cn/problem/P10424
题目描述
一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。
给定一个正整数 N N N,请计算从 1 1 1 到 N N N 一共有多少个好数。
输入格式
一个整数 N N N。
输出格式
一个整数代表答案。
输入输出样例 #1
输入 #1
24
输出 #1
7
输入输出样例 #2
输入 #2
2024
输出 #2
150
说明/提示
样例 1 解释
24 24 24 以内的好数有 1 , 3 , 5 , 7 , 9 , 21 , 23 1,3,5,7,9,21,23 1,3,5,7,9,21,23,一共 7 7 7 个。
数据规模与约定
- 对于 10 % 10\% 10% 的测试数据, 1 ≤ N ≤ 100 1 \leq N \le 100 1≤N≤100。
- 对于全部的测试数据, 1 ≤ N ≤ 1 0 7 1 \le N \leq 10^7 1≤N≤107。
解题思路
直接对1-n
内的每一个数字进行判断即可,若奇数位为偶数或者偶数位为奇数则返回false
,全部位置判断完毕则返回true
。
AC Code
#include <bits/stdc++.h>
using namespace std;
bool check(int num){
int i=1;
while(num){
int tmp = num%10;
if(i){
if(tmp%2==0){
return false;
}
}
else {
if(tmp%2){
return false;
}
}
i^=1;
num/=10;
}
return true;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n;
cin >> n;
int res = 0;
for(int i=1;i<=n;i++){
if(check(i)){
res++;
}
}
cout << res;
return 0;
}