1 条题解
-
0
📝 题目大意
给定 和 ,构造一个长度为 的整数数列,使得其中恰好有 个正整数、 个负整数,所有元素互不相同、非零、绝对值不超过 ,且总和为 。
💡 解题思路
-
题目分析:
- 数据范围 很小,构造空间充裕。
- 核心要求是总和为 ,即正数之和等于负数之和的绝对值。
- 可以证明一定存在解,我们只需构造任意一组。
-
算法推导: 设 ,即 到 的等差数列和。
核心思想:让正数部分的总和恰好为 ,负数部分的总和恰好为 ,这样总和自动为 。
- 正数部分(共 个):先取 这 个自然数,它们的和为 。最后一个正数取 ,这样正数总和 = 。
- 负数部分(共 个):先取 这 个负整数,它们的和为 。最后一个负数取 ,这样负数总和 = 。
正确性说明:
- 所有数互不相同:正数部分全是正数,负数部分全是负数,正负之间不可能重复。正数内部,前 个是 ,最后一个 至少为 (当 时等于 ,当 时大于 ),不会与前 个重复。负数部分同理。
- 范围合规:,,所有数绝对值远小于 。
-
边界与细节:
- 当 时,正数部分只有一个数 (因为 ),输出 即可。
- 当 时同理,负数部分只有一个数 。
- 注意使用
long long避免在计算 时溢出(虽然 时int也够,但std.cpp采用了更安全的类型)。
⏱️ 复杂度分析
- 时间复杂度:,需要依次输出 个数。
- 空间复杂度:,仅使用常数个辅助变量。
💻 标准代码 (C++)
#include <bits/stdc++.h> using namespace std; int main(){ long long a, b, c; // 使用 long long 防止中间计算溢出 cin >> a >> b; // c = max(A, B) 的前缀和,即 1 + 2 + ... + max(A, B) c = max(a, b); c = c * (c + 1) / 2; // 输出 A 个正数:前 A-1 个是 1, 2, ..., A-1 for(int i = 1; i <= a - 1; i++) cout << i << " "; // 最后一个正数 = c - (1 到 A-1 的和) = c - A*(A-1)/2,保证正数总和为 c cout << c - a * (a - 1) / 2 << " "; // 输出 B 个负数:前 B-1 个是 -1, -2, ..., -(B-1) for(int i = 1; i <= b - 1; i++) cout << -i << " "; // 最后一个负数 = -(c - (1 到 B-1 的和)) = -(c - B*(B-1)/2),保证负数总和为 -c cout << -(c - b * (b - 1) / 2) << endl; return 0; } -
信息
- ID
- 859
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者