题目链接:点这里
题目描述:
一个整数总可以拆分为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。
思路:
使用动态规划的思想,最终得到代码中的两个式子,
f(2m+1) = f(2m)
f(2m) = f(2m-1)+f(m)
具体的思路,搬运一下评论里的(原文在题目链接评论中,举的例子比较好理解):
思路:通过递推公式,划分为子问题求解。
问题:一个整数拆分为2的幂的和。即(1, 2, 2^2, 2^3,..., 2^k),包含1个奇数和k个偶数。
对于N,分为两种情况:
1)N为奇数(2m+1),则每个拆分结果必然至少有一个1,因为只通过k个偶数无法组成奇数。所以f(2m+1) = f(2m)
例如 f(5) 1+(4) 1+(2+2) 1+(1+1+2) 1+(1+1+1+1+1)
f(4) 4 2+2 1+1+2 1+1+1+1+1
2) N为偶数(2m),拆分同样分为两类:拆分结果中包含1和拆分结果不包含1
a) 拆分结果包含1 (奇拆分):所有的拆分数目为f(2m-1),同上
b) 拆分结果不包含1(偶拆分):拆分数目为f(m)。 拆分结果不包含1,说明是拆分成了k个偶数,那么对每一种拆分结果都除以2,并不会影响整体拆分的数目。但是每个拆分结果的sum都变成了m,即每个2m的偶拆分都变成了m的拆分。同样对m的每种拆分结果都乘以2,拆分结果的sum都变成了2m且不包含1。即m的拆分和2m的偶拆分一一对应。
例如f(8) (不包含1的拆分有四种) 8 4+4 2+2+4 2+2+2+2
f(4)(所有拆分有四种) 4 2+2 1+1+2 1+1+1+1
f(2m) = f(2m-1) + f(m)综上所述:
f(2m+1) = f(2m)
f(2m) = f(2m-1) + f(m)
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9;
const int maxn = 1e6+2;
int f[maxn];
int main(){
int n;
f[1] = 1;
for(int i=2;i<=1e6;i++){
if(i%2==1)
f[i] = f[i-1];
else
f[i] = (f[i-1]+f[i/2])%mod;
}
while(cin >> n){
cout << f[n] << endl;
}
return 0;
}