题目描述:P1147 连续自然数和
解题思路
解题思路
1、题目要求 $l + (l+1) + (l+2) + \ldots + (r-1) + r = M$,可利用等差数列化简:$\frac{(首项 + 末项) * 项数}{2}$,即该题求所有满足 $(l + r)(r - l + 1) = 2M$ 的 $l, r$
2、等式左侧为两个整数,所以左侧的 $(l + r)$ 和 $(r - l + 1)$ 必然都是 $2M$ 的因数。此时求出 $2M$ 的所有因数(记因数至 $x[]$ 数组),便可将数据范围缩小至 $2\sqrt{2M}$ 之内
3、由于直接枚举 $l, r$ 范围太大,而 $x[]$ 的下标范围显然更小。所以令 $x[i] = l + r$ ,$x[j] = r - l + 1$,联立整理两式得 $r = \frac{(x[i] + x[j] + 1)}{2}$,$l = x[i] - r$,此时 $l, r$ 为答案
4、但要使得答案存在,则必须满足前述的 $l, r$ 为整数这一条件,参照两个化简式,需要使 $r$ 为整数。所以必须满足 $(x[i] + x[j] + 1)$ 为 $2$ 的倍数
代码实现
代码实现
#include <bits/stdc++.h> using namespace std; void solve() { int m; cin >> m; // 求 2 * M 的所有因子 vector<int> x; // 记录 2 * M 的所有因子 for (int i = 2; i <= 2 * m / i; i++) { if (2 * m % i) continue; x.push_back(i); // 小因子 if (i != 2 * m / i) x.push_back(2 * m / i); // 大因子 } // 枚举答案 vector<pair<int, int>> ans; for (auto &xi : x) { for (auto &xj : x) { // 如果不满足整数条件 if ((xi + xj - 1) % 2) continue; int r = (xi + xj - 1) / 2, l = xi - r; // 判断 l, r 是否合法 if (l >= 0 && l <= r && (l + r) * (r - l + 1) == 2 * m) ans.push_back({l, r}); } } // 排序输出 sort(ans.begin(), ans.end()); for (auto &[l, r] : ans) cout << l << ' ' << r << '\n'; } int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int T = 1; // cin >> T; while (T--) solve(); return 0; }
如果较为紧急,建议添加微信或QQ,并注明来意
评论系统可能加载较慢,请耐心等待或刷新重试