HDOJ-2709 Sumsets(遞推)
阿新 • • 發佈:2018-11-11
題目:HDOJ-2709
題目描述:
給出一個正整數N,求出N能由多少種2的冪次方(1,2,4,8…)之和的組合得到。
(1 <= N <= 1,000,000)(由於資料過大,所有答案只取後9位。)
例如當N等於7,有6種方案
1)1+1+1+1+1+1+1
2) 1+1+1+1+1+2
3) 1+1+1+2+2
4) 1+1+1+4
5) 1+2+2+2
6) 1+2+4
思路:
當N為奇數(分解方案中必有1):則N-1為偶數,易知N的所有分解方案都是在N-1的基礎上+1
所以此時f(N)=f(N-1)
當N為偶數:
①首先同樣的在N-1的所有分解方案上+1,可以得到部分的分解方案。
②但是,還是存在分解方案內不含1的情況,經分析可以知道將N/2的所有分解方案*2,就得到了所有不含1的分解方案。
所以此時f(N)=f(N-1)+f(N/2)
舉個例子便於理解:
N=2,2種方案:①2 ②1+1
N=3,2種方案:①2+1 ②1+1+1
可以看到N=3時,都是在N=2的基礎上+1。
那麼當N=4時,
首先是在N=3的基礎上+1,得到兩種:①2+1+1 ②1+1+1+1
再者就是將N=2的方案*2,又得到兩種:③4 ④2+2
一共4種方案
+1提供了包含1的方案,*2提供了不包含1的方案,兩者得到依舊是2的冪次方的求和組合。
以下程式碼:
#include<cstdio>
using namespace std;
int main()
{
__int64 f[1000001];
int i, n;
f[1] = 1;
f[2] = 2;
for (i = 3; i <= 1000000; i++)
{
if (i % 2 == 1)
f[i] = f[i - 1]; //為奇數
else
f[i] = f[i - 1] + f[i / 2]; //為偶數
f[i] %= 1000000000; //取最後9位
}
while (scanf("%d", &n)!=EOF)
printf("%I64d\n", f[n]);
return 0;
}