返回题解分享
讨论 / 题解分享/ 帖子详情

等差数列 - 题解

解决思路



  1. 好数序列分析
- 如果公差 $D < 0$,序列递减,需将 $A$ 转化为第 $N$ 项的值,将 $D$ 取绝对值以便统一处理递增序列。
- 转化后,序列形式为 $A, A+D, A+2D, \ldots, A+(N-1)D$。
  1. 二分查找
- 将好数序列视为一个递增数组,使用二分查找定位 $X$ 在序列中的最近位置。
- 二分查找的目标是找到一个索引 $k$,使得 $A + k \cdot D$ 最接近 $X$。
  1. 检查附近的项
- 由于二分查找找到的位置可能不是最优解,还需检查二分附近的几项(例如 $k-1, k, k+1$),找出与 $X$ 的最小绝对差。
  1. 时间复杂度
- 构造序列的一般项计算复杂度为 $O(1)$。
- 二分查找的时间复杂度为 $O(\log N)$。
- 最多检查 10 项附近值,时间复杂度为常数级。
- 总复杂度为 $O(\log N)$。

代码详解



  1. 输入数据预处理
- 如果 $D < 0$,将序列起始值 $A$ 转化为最后一项 $A + (N-1)D$,并将 $D$ 取绝对值。
- 这样,序列转化为递增序列。
  1. 二分查找
- 定义查找范围为 $[0, N-1]$,取中间值计算该项对应的数值。
- 比较中间项和 $X$ 的大小,调整查找范围,直到找到最近的位置。
  1. 周边值检查
- 检查二分查找附近的几项(例如 $k-5$ 到 $k+5$,确保不越界),计算与 $X$ 的绝对差。
  1. 输出结果
- 输出最小绝对差。

#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 阅读
回复 (0)
默认 最新
暂无回复,快来抢沙发!