解决思路
- 好数序列分析:
- 转化后,序列形式为 $A, A+D, A+2D, \ldots, A+(N-1)D$。
- 二分查找:
- 二分查找的目标是找到一个索引 $k$,使得 $A + k \cdot D$ 最接近 $X$。
- 检查附近的项:
- 时间复杂度:
- 二分查找的时间复杂度为 $O(\log N)$。
- 最多检查 10 项附近值,时间复杂度为常数级。
- 总复杂度为 $O(\log N)$。
代码详解
- 输入数据预处理:
- 这样,序列转化为递增序列。
- 二分查找:
- 比较中间项和 $X$ 的大小,调整查找范围,直到找到最近的位置。
- 周边值检查:
- 输出结果:
#include<bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
long long x, a, d, n;
cin >> x >> a >> d >> n;
// 处理递减序列,将其转为递增序列
if (d < 0) {
a = a + d * (n - 1);
d = -d;
}
// 二分查找最近的项
long long l = 0, r = n - 1;
while (l <= r) {
long long m = (l + r) / 2;
if (a + d * m < x) {
l = m + 1;
} else {
r = m - 1;
}
}
// 检查附近的项
long long res = LLONG_MAX;
for (long long i = max(0LL, l - 5); i <= min(n - 1, l + 5); i++) {
res = min(res, abs(a + d * i - x));
}
// 输出结果
cout << res << '\n';
return 0;
}import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long x = sc.nextLong();
long a = sc.nextLong();
long d = sc.nextLong();
long n = sc.nextLong();
// 转换递减为递增序列
if (d < 0) {
a = a + d * (n - 1);
d = -d;
}
// 二分查找最近的位置
long l = 0, r = n - 1;
while (l <= r) {
long m = (l + r) / 2;
if (a + d * m < x) {
l = m + 1;
} else {
r = m - 1;
}
}
// 检查附近的值
long res = Long.MAX_VALUE;
for (long i = Math.max(0, l - 5); i <= Math.min(n - 1, l + 5); i++) {
res = Math.min(res, Math.abs(a + d * i - x));
}
// 输出结果
System.out.println(res);
}
}def closest_good_number(x, a, d, n):
# 转换递减为递增序列
if d < 0:
a = a + d * (n - 1)
d = -d
# 二分查找最近的位置
l, r = 0, n - 1
while l <= r:
m = (l + r) // 2
if a + d * m < x:
l = m + 1
else:
r = m - 1
# 检查附近的值
res = float('inf')
for i in range(max(0, l - 5), min(n - 1, l + 5) + 1):
res = min(res, abs(a + d * i - x))
# 输出结果
return res
# 输入
x, a, d, n = map(int, input().split())
print(closest_good_number(x, a, d, n))
0 回复
0 转发
0 喜欢
2 阅读



