[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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章