牛客网计算机考研复试-KY8-整数拆分

题目链接:点这里


题目描述:
一个整数总可以拆分为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;
}

原文地址:https://www.cnblogs.com/123-wind/p/14296766.html