题意:给出数字n,找由2的幂次数组成的组合,此组合中的数加和后为n;结果要求输出这样的组合个数;如果得到的结果很大,保留后9位。如:n=7
可以看到下图6个组合中的数均是由2的某次幂组成的(2^0=1, 2^1=2,2^2=4,….)
分析:写出n比较小的情况进行分析
- n=1
1) 1 - n=2
1) 1 1
2) 2 - n=3
1) 1 1 1
2) 1 2 - n=4
1) 1 1 1 1
2) 1 1 2
3) 2 2
4) 4 - n=5
1) 1 1 1 1 1
2) 1 1 1 2
3) 1 2 2
4) 1 4 - n=6
1) 1 1 1 1 1 1
2) 1 1 1 1 2
3) 1 1 2 2
4) 1 1 4
5) 2 2 2
6) 2 4 - n=7
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=8
1) 1 1 1 1 1 1 1 1
2) 1 1 1 1 1 1 2
3) 1 1 1 1 2 2
4) 1 1 1 1 4
5) 1 1 2 2 2
6) 1 1 2 4
7) 2 2 2 2
8) 2 2 4
9) 4 4
10) 8
观察之后会发现n为奇数的那些组合的开头为1,而n为偶数的组合开头分为以1开头和非1开头;
观察n=6和n=7 会发现两个数的组合个数是相同的,n=7 可以看作将n=6的组合开头加入一个1;可继续比较n=3和n=2,n=5和n=4。。。。
观察n=8与n=7中以1开头的部分可以看出,n=7的组合开头加入1后得到n=8开头为1的情况,再看n=8以非1开头的组合部分,其值是8/2即n=4的组合的值的两倍,组合个数与n=4相同。
综合以上:- n=1 f(n)=1
- n%2==1 f(k)=f(k-1)
- n%2==0 f(k)=f(k-1)+f(k/2)
#include<iostream>
using namespace std;
int s[1000100];
int main() {
int n;
s[1] = 1;
cin >> n;
for (int i = 2; i <= n; ++i) {
if (i % 2 == 0) {
s[i] = (s[i - 1] + s[i / 2]) % 1000000000;
continue;
}
s[i] = s[i - 1];
}
cout << s[n] << endl;
system("pause");
return 0;
}