问题描述理解
给定正整数M,寻找所有连续的正整数序列,序列的累加和等于M,且每个序列至少包含两个数。输出需按序列起始数字升序排列,每行包含起始和结束数字。
数学原理分析
连续正整数序列的和可通过等差数列求和公式表示。设序列起始数为a,长度为k,则和S满足:
[ S = \frac{k \times (2a + k - 1)}{2} ]
给定S=M,需解方程:
[ M = \frac{k \times (2a + k - 1)}{2} ]
变形后得到a的表达式:
[ a = \frac{2M/k - k + 1}{2} ]
要求a为正整数,需满足以下条件:
- ( 2M/k - k + 1 )为偶数
- ( k \leq \sqrt{2M} )
- ( a > 0 )
算法设计思路
双指针法
维护滑动窗口[l, r],动态调整窗口范围使窗口内和等于M。若当前和小于M,扩大右边界;若大于M,缩小左边界。
数学推导法
枚举可能的序列长度k(2 ≤ k ≤ √(2M)),检查是否存在整数a满足条件。
代码实现解析
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
LL n;
cin >> n;
LL r = 2, l = 1;
LL sum = l + r;
while (l <= n / 2) {
if (sum < n) {
r++;
sum += r;
} else if (sum > n) {
sum -= l;
l++;
} else {
cout << l << ' ' << r << endl;
sum -= l;
l++;
}
}
}
关键点
- 初始化:l=1, r=2,sum初始为l + r。
- 循环条件:l不超过n/2,避免无效遍历。
- 动态调整:根据sum与n的关系移动指针,输出满足条件的区间。
复杂度分析
- 时间复杂度:O(M),最坏情况下需遍历到M/2。
- 空间复杂度:O(1),仅使用常数空间。
边界条件与优化
- 输入范围:确保M ≥ 3(最小有效输入为3,序列1+2)。
- 提前终止:当l超过n/2时终止循环。
- 数学优化:结合数学推导筛选可能的k值,减少枚举次数。
示例验证
输入M=10000时,部分输出:
18 142
297 328
388 412
1998 2002
验证1998到2002的和:
[ 1998 + 1999 + 2000 + 2001 + 2002 = 10000 ]
扩展思考
- 大数据处理:若M范围扩大到1e12,数学方法需优化枚举k的范围,仅检查M的因数。
- 多解顺序:双指针法天然保证按起始数升序输出。
- 序列长度限制:可扩展问题,限制序列长度在特定范围内求解。
363

被折叠的 条评论
为什么被折叠?



