http://acm.hdu.edu.cn/showproblem.php?pid=2709
7
6
一、 DP解法(这应该是标准解法了 本人第一次 碰到这类题 也是用DP)
思路:
1.如果n为奇数,那么所求的分解结果中必含有1,因此,直接将n-1的分拆结果中添加一个1即可 为s[n-1]
2.如果n为偶数,那么n的分解结果分两种情况:
a) 含有1:这种情况可以直接在n-1的分解结果中添加一个1即可 s[n-1]
b) 不含1:那么,分解因子的都是偶数,将每个分解的因子都除以2,刚好是n/2的分解结果,并且可以与之一一对应,这种情况有 s[n/2]
所以,状态转移方程为
如果i为奇数 s[i] = s[i-1]
如果i为偶数 s[i] = s[i-1] + s[i/2]
二、这是递推的方法 (很简洁 偶然看到这个代码 只想说牛X)
如果所求的n为奇数,那么所求的分解结果中必含有1,因此,直接将n-1的分拆结果中添加一个1即可 为s[n-1] 如果所求的n为偶数,那么n的分解结果分两种情况 1.含有1 这种情况可以直接在n-1的分解结果中添加一个1即可 s[n-1] 2.不含有1 那么,分解因子的都是偶数,将每个分解的因子都除以2,刚好是n/2的分解结果,并且可以与之一一对应,这种情况有 s[n/2] 所以,状态转移方程为 如果i为奇数, s[i] = s[i-1] 如果i为偶数 s[i] = s[i-1] + s[i/2]
#include <stdio.h>
int n,s[1000001], i = 3;
int main()
{
s[1] = 1;
s[2] = 2;
while (i <= 1000000)
{
s[i++] = s[i-1];
s[i++] = (s[i-2] + s[i >> 1]) % 1000000000;// >>是位运算 的左移运算 自行百度吧
}
while(scanf("%d",&n) != EOF)
printf("%d\n", s[n]);
return 0;
}