洛谷P1147 连续自然数和 题解 枚举

题目链接:https://www.luogu.com.cn/problem/P1147

题目大意:
给你一个数 \(M\) ,求有多少对连续自然数对之和为 \(M\),输出这列连续自然数对的首项和末项。

解题思路:
枚举连续自然数对的元素个数 \(i\)
因为连续自然数对的元素个数越多,则首项越小,所以我们从 \(M\)\(2\) 枚举个数 \(i\)
在已知元素个数的情况下,我们设首项为 \(a\) ,则有:

\[a+a+1+ \dots + a+i-1 = M\]

\[\Rightarrow a \times i + 1+2+ \dots +i-1 = M\]

\[\Rightarrow a \times i + \frac{i \times (i-1)}2 = M\]

\[\Rightarrow a = \frac{M-\frac{i(i-1)}2}{i}\]

所以上述公式中的分母能被分子整除,并且计算得到的 \(a > 0\) ,则找到一个连续自然数对,其首项为 \(a\) ,末项为 \(a+i-1\)

需要注意的是,因为 \(M \le 2 \times 10^6\) ,所以 \(i \times i / 2\) 可能会超 int,所以在处理的时候有两种解决办法:

  • 一种是开long long;
  • 另一种是先判断 \((i-1)/2 > m/i\) 是否成立,如果成立就说明首项 \(\le 0\) ,就跳过这步往更小的区间去判断。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
int m;
int main() {
    cin >> m;
    for (int i = m; i > 1; i --) {
        if ((i-1)/2 > m/i) continue;
        if ( (2*m-i*(i-1)) % (2*i) == 0 ) {
            int a = (2*m-i*(i-1))/(2*i);
            int b = a + i - 1;
            if (a > 0)
                cout << a << " " << b << endl;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/quanjun/p/12006300.html