題目描述:
乙個整數總可以拆分為2的冪的和,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1+1+1+1+1+1+1 總共有六種不同的拆分方式。 再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。 用f(n)表示n的不同拆分的種數,例如f(7)=6. 要求編寫程式,讀入n(不超過1000000),輸出f(n)%1000000000。
輸入描述:
每組輸入包括乙個整數:n(1<=n<=1000000)。
輸出描述:
對於每組資料,輸出f(n)%1000000000。
輸入
7輸出
6解題思路(摘):
記f(n)為n的劃分數,我們有遞推公式:
f(2m + 1) =f(2m)f(2m) = f(2m - 1) + f(m)
初始條件:f(1) = 1。
證明:
證明的要點是考慮劃分中是否有1。
記:
a(n) = n的所有劃分組成的集合,
b(n) = n的所有含有1的劃分組成的集合,
c(n) = n的所有不含1的劃分組成的集合,
則有: a(n) = b(n)∪c(n)。
又記:f(n) = a(n)中元素的個數,
g(n) = b(n)中元素的個數,
h(n) = c(n)中元素的個數,
易知: f(n) = g(n) + h(n)。
我們先來證明: f(2m + 1) = f(2m),
首先,2m + 1 的每個劃分中至少有乙個1,去掉這個1,就得到 2m 的乙個劃分,故 f(2m + 1)≤f(2m)。
其次,2m 的每個劃分加上個1,就構成了 2m + 1 的乙個劃分,故 f(2m)≤f(2m + 1)。
綜上,f(2m + 1) = f(2m)。
接著我們要證明: f(2m) = f(2m - 1) + f(m),
把 b(2m) 中的劃分中的1去掉乙個,就得到 a(2m - 1) 中的乙個劃分,故 g(2m)≤f(2m - 1)。
把 a(2m - 1) 中的劃分加上乙個1,就得到 b(2m) 中的乙個劃分,故 f(2m - 1)≤g(2m)。
綜上,g(2m) = f(2m - 1)。
把 c(2m) 中的劃分的元素都除以2,就得到 a(m) 中的乙個劃分,故 h(2m)≤f(m)。
把 a(m) 中的劃分的元素都乘2,就得到 c(2m) 中的乙個劃分,故 f(m)≤h(2m)。
綜上,h(2m) = f(m)。
所以: f(2m) = g(2m) + h(2m) = f(2m - 1) + f(m)。
**:
#include #include#include
#include
using
namespace
std;
long ans[1000001
];//
n表示ans計算到哪個數字
intn;
/*f(2m + 1) = f(2m),
f(2m) = f(2m - 1) + f(m)
*/void caculate(int n, int
n)
else
ans[i] = ans[i] % 1000000000
; }
}int
main()
caculate(n,n);
cout
<< ans[n]
}return0;
}
牛客網刷題 整數拆分
題目描述 乙個整數總可以拆分為2的冪的和,例如 7 1 2 4 7 1 2 2 2 7 1 1 1 4 7 1 1 1 2 2 7 1 1 1 1 1 2 7 1 1 1 1 1 1 1 總共有六種不同的拆分方式。再比如 4可以拆分成 4 4,4 1 1 1 1,4 2 2,4 1 1 2。用f n...
牛客網 進製轉換(大整數)
將乙個長度最多為30位數字的十進位製非負整數轉換為二進位制數輸出。輸入描述 多組資料,每行為乙個長度不超過30位的十進位製非負整數。注意是10進製數字的個數可能有30個,而非30bits的整數 輸出描述 每行輸出對應的二進位制數。只是十進位制轉二進位制的話,並沒有難度。就是依次去 2,直到被除數為0...
牛客網C語言整數奇偶排序
輸入10個整數,彼此以空格分隔。重新排序以後輸出 也按空格分隔 要求 1.先輸出其中的奇數,並按從大到小排列 2.然後輸出其中的偶數,並按從小到大排列。任意排序的10個整數 0 100 彼此以空格分隔。可能有多組測試資料,對於每組資料,按照要求排序後輸出,由空格分隔。1.測試資料可能有很多組,請使用...