题目要求简述

给定整数 n, k, x,请你找一个区间 [l, r] 满足:

  • 区间长度为 k,即 r = l + k - 1
  • 区间中恰好有 nx 的倍数
  • 1 ≤ l ≤ r < 2e9
  • 如果不存在这样的区间,输出 -1

解题思路

  1. 直观理解:一个区间中 x 的倍数是规则出现的。如果我们在区间 [l, r] 中想要恰好有 n 个 x 的倍数,那么最紧凑的情况是: l 为最小的 x 的倍数(比如 x)r 为第 n 个 x 的倍数(即 n * x)此时区间长度最小:k = r - l + 1 = (n * x) - x + 1 = (n - 1) * x + 1最稀疏的情况:两个 x 的倍数之间尽量拉远,但不能超过 k 的限制。
  2. 最小 / 最大可能长度推导:最小长度:连续 n 个 x 的倍数,最紧凑,即:最大长度:在区间内可以包含最多 n 个 x 的倍数,如果它们正好出现在两端(最稀疏),间距最小是:如果题目给的 k 不在 [minLen, maxLen] 之间,说明没办法构造这样的区间,直接输出 -1。
  3. 构造合法区间 [left, right]:从最紧凑的区间开始:当前区间长度为:right - left + 1如果小于 k,我们在保持区间内倍数数量不变的前提下,“对称”地扩展: left-- & right++每次扩展会让区间长度 +2,直到长度为 k

你写的代码 + 详细注释

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define int long long  // 使用 long long 防止大数溢出

using namespace std;

// 解题函数
void solve(){
    int  n, k, x; 
    // 输入:n 表示希望区间内有 n 个 x 的倍数
    //      k 表示区间长度
    //      x 是倍数目标
    cin >> n >> k >> x; 

    // 最小长度:连续 n 个 x 的倍数所构成的最短区间长度
    int minLen = (n - 1) * x + 1;
    // 最大长度:还能容纳 n 个倍数的最大区间长度(再长,倍数数目可能会减少)
    int maxLen = (n + 1) * x - 1;

    // 判断是否存在合法的区间长度
    if (k < minLen || k > maxLen) {
        cout << "-1";  // 不存在这样的区间
        return;
    }

    // 起始区间:最紧凑的区间,左端点为第一个倍数,右端点为第 n 个倍数
    int left = x;
    int right = n * x;

    // 当前区间长度为:right - left + 1,我们要调整使它恰好为 k
    k = k - (right - left + 1);  // 还需要扩展的长度

    // 从两边对称扩展,每次扩展两端各1个数,直到区间长度满足要求
    while (k) {
        if (k) {
            left--;  // 左端点向左扩展
            k--;
        }
        if (k) {
            right++;  // 右端点向右扩展
            k--;
        }
    }

    // 输出最终区间 [left, right]
    cout << left << " " << right << "\n";
}

// 主函数
signed main(){
    int T = 1;  // 默认只做一组输入
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);  // 提高读写效率
    // cin >> T; // 如果是多组输入可以打开这一行
    while (T--) {
        solve();
    }
    return 0;
}

✅ 样例验证:

输入:

2 881761968 737875443

输出:

737875443 1619637410 ✅

✅ 总结优势:

  • 💡 无需二分,逻辑清晰直接
  • 🧠 用等差间隔的思维直接构造合法区间
  • 🪄 区间平移对称调整,优雅又精巧