HDOJ-2709 Sumsets(递推)

版权声明:个人学习笔记记录 https://blog.csdn.net/Ratina/article/details/83958554

题目: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;
}

猜你喜欢

转载自blog.csdn.net/Ratina/article/details/83958554