[SHOI2002]N的连续数拆分 题解
一道比较简单的数学题。
题目问我们正整数 \(n\) 可以被多少组连续的正整数拆分。那么这些连续的正整数会组成一个公差为 \(1\) 的等差数列。
设数列的首项为 \(a\),末项为 \(b\),则该等差数列的和为 \(\dfrac{(a+b)(b-a+1)}{2}\)。
然后来推一波柿子:
\[\because \dfrac{(a+b)(b-a+1)}{2}=n
\]
\[\therefore (a+b)(b-a+1)=2n
\]
\[\therefore (a+b)(b-a+1)\bmod 2=0
\]
\[\because \text{两数和、差的奇偶性相同}
\]
\[\therefore (a+b)\text{ 和 }(b-a)\text{ 的奇偶性相同}
\]
\[\therefore (a+b)\text{ 和 }(b-a+1)\text{ 的奇偶性不同}
\]
由此,我们只需要枚举 \((a+b)\),判断其是否为 \(2n\) 的因子。若是,则求出 \((b-a+1)\)。如果 \((a+b)\) 和 \((b-a+1)\) 的奇偶性不同,则方案数增加。
时间复杂度为 \(O(\sqrt{n})\),常数为 \(\sqrt{2}\)。
\(11\) 行代码(未压行):
#include <bits/stdc++.h>
using namespace std;
long long n;
int main() {
scanf("%lld",&n);
n<<=1; // 之后不需要使用 n 了,只需要用 2n,故直接将 n 乘上 2
int ans=0,m=sqrt(n);
for (register int i=1,j;i<=m;i++) ans+=!(n%i)&&(i&1)^(n/i&1); // 位运算。等价于 if (n%i==0&&i%2!=n/i%2) ans++;
printf("%d",ans);
return 0;
}
转载是允许的,但是除了博主同意的情况下,必须在文章的明显区域说明出处,否则将会追究其法律责任。