qzhs 题解分享 · 2024/12/25
等差数列 - 题解
解决思路 1. 好数序列分析: - 如果公差 $D < 0$,序列递减,需将 $A$ 转化为第 $N$ 项的值,将 $D$ 取绝对值以便统一处理递增序列。 - 转化后,序列形式为 $A, A+D, A+2D, \ldots, A+(N-1)D$。 2. 二分查找: - 将好数序列视为一个递增数组,使用二分查找定位 $X$ 在序列中的最近位置。 - 二分查找的目标是找到一个索引 $k$,使得 $A + k \cdot D$ 最接近 $X$。 3. 检查附近的项: - 由于二分查找找到的位置可能不是最优解,还需检查二分附近的几项(例如 $k-1, k, k+1$),找出与 $X$ 的最小绝对差。 4. 时间复杂度: - 构造序列的一般项计算复杂度为 $O(1)$。 - 二分查找的时间复杂度为 $O(\log N)$。 - 最多检查 10 项附近值,时间复杂度为常数级。 - 总复杂度为 $O(\log N)$。 代码详解 1. 输入数据预处理: - 如果 $D < 0$,将序列起始值 $A$ 转化为最后一项 $A + (N-1)D$,并将 $D$ 取绝对值。 - 这样,序列转化为递增序列。 2. 二分查找: - 定义查找范围为 $[0, N-1]$,取中间值计算该项对应的数值。 - 比较中间项和 $X$ 的大小,调整查找范围,直到找到最近的位置。 3. 周边值检查: - 检查二分查找附近的几项(例如 $k-5$ 到 $k+5$,确保不越界),计算与 $X$ 的绝对差。 4. 输出结果: - 输出最小绝对差。 ```cpp #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; } ``` ```java 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); } } ``` ```python 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 3