九度1084解題報告

http://ac.jobdu.com/problem.php?pid=1084 整數拆分的題。

根據這幾天的做清華真題的情況,可以看出,清華超愛出數學類的題目,考察學生的數學基礎和找規律的能力。這道題,乍一看是要找個什麼公式或者規律來解決,其實僅僅用dp就可以解決,也就是說,要找出拆分種類的遞推規律。本題主要有兩條規律,即要分奇偶討論。

當要拆分的數爲奇數時,其拆分種類與上一個偶數相同,其實就是在上一個數的各拆分上+1,我一開始懷疑,如果原拆分中也含1,將兩個1換成一個2,會不會又是一種新的拆分,事實上不會,因爲偶數的拆分中1一定是成對出現的,如果新加的1與原來的一個1湊成一對,那麼把多出來的一個單1去掉,一定是上一個偶數的一個拆分。因此,一個奇數的拆分與它上一個偶數的拆分一定一樣多。這個規律比較明顯。

而當要拆分的數爲偶數時,規律就比較難找了。上一個奇數的各拆分加1肯定構成新的拆分,而上一個奇數的帶不成對1 的拆分,與新加的1湊成一對,也構成新的拆分,進而不斷向上湊,很難得出有多少拆分。於是,我們考慮另一種分類方法:將拆分分爲帶1的拆分和不帶1的拆分。不帶1的拆分,最小數爲2,故整個拆分可以被2整除,因此數n不帶1的拆分數應該和n/2的所有拆分相等。而帶1的拆分,其實和上一個奇數相同,因爲帶1的拆分至少有兩個1,去掉一個1後,即n-1的拆分。

找到了規律,用dp就很方便了,代碼如下:

#include <stdio.h>
#define MAX 1000002
#define MOD 1000000000

long long dp[MAX];

int main()
{
	dp[0]=dp[1]=1;
	for (int i=1;i<=500000;++i)
	{
		dp[2*i]=(dp[2*i-1]+dp[i])%MOD;
		dp[2*i+1]=dp[2*i]%MOD;
	}
	int n;
	while (scanf("%d",&n)!=EOF)
	{
		printf("%lld\n", dp[n]);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章