$$
\begin{aligned}
n &= \dfrac{(a + (a + k - 1)) \times k}{2} \\
&= \dfrac{(2a + k - 1) \times k}{2}
\end{aligned}
$$
从题目中得知,我们已知和为 n,
那么就要求上述方程的正整数解,但有两个未知数 a, k,一种简单的思路是:枚举其中一个数,那么另外一个数字就能计算出来了,我们只需验证得到的解是否合法即可,这里的合法是指解出的
a, k
应该是正整数。
相比之下,枚举连续数字的个数 k 比枚举起点 a 要容易一些,将公式变形,即
$$
a = \dfrac{\cfrac{2n}{k} + 1 - k}{2}
$$
那么还剩下一个问题是,枚举到什么时候终止呢?换而言之,k最大取值是多少?
不难发现,在和一定的情况下,以 1 为起点得到的数列是最长的,即 a = 1 代入时得到的 k 最大,所以当我们计算到 a < 1 即可终止。
1 2 3 4 5 6 7 8 9 10 11
# Code language: Python classSolution: defconsecutiveNumbersSum(self, n: int) -> int: cnt = 1 for k inrange(2, n): a = (2 * n // k + 1 - k) // 2 if a < 1: break elif n == (2 * a + k - 1) * k // 2: cnt += 1 return cnt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Code language: Java classSolution { publicintconsecutiveNumbersSum(int _n) { // (2 * a + k - 1) * k / 2 = n // (2 * n / k + 1 - k) / 2 = a intcnt=1; for (longk=2, n = _n; ; ++k) { longa= (2 * n / k + 1 - k) / 2; if (a < 1) break; longs= (2 * a + k - 1) * k / 2; if (s == n) ++cnt; } return cnt; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Code language: C++ classSolution { public: intconsecutiveNumbersSum(int n){ int cnt = 1; for (long k = 2; ; ++k) { long a = (2 * n / k + 1 - k) / 2; if (a < 1) break; long s = (2 * a + k - 1) * k / 2; if (s == n) ++cnt; } return cnt; } };
1 2 3 4 5 6 7 8 9 10 11
// Code language: C intconsecutiveNumbersSum(int n){ int cnt = 1; for (long k = 2; ; ++k) { long a = (2 * n / k + 1 - k) / 2; if (a < 1) break; long s = (2 * a + k - 1) * k / 2; if (s == n) ++cnt; } return cnt; }
1 2 3 4 5 6 7 8 9 10 11 12 13
// Code language: C# publicclassSolution { publicintConsecutiveNumbersSum(int n) { int cnt = 1; for (long k = 2; ; ++k) { long a = (2 * n / k + 1 - k) / 2; if (a < 1) break; long s = (2 * a + k - 1) * k / 2; if (s == n) ++cnt; } return cnt; } }