描述:
一个整数可以拆分为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。
分析:
对于奇数 n = 2k+1, 它的拆分的第一项一定是1, 考虑去掉这个1,其实就一一对应于
2k的拆分,因此f(2k+1) = f(2k)。
对于偶数n = 2k: 考虑有1和没有1的拆分。有1的拆分,与(2k-1)的拆分一一对应,与上面
奇数的情况理由相同:没有1的拆分,将每项除以2,正好一一对应于k的所有拆分,因此
f(2k) = f(2k-1) + f(k)。
最终结果只要求除以十亿的余数,在int的表示范围内,因此也不需要大数运算。注意余数的
性质:(a+b)%m = (a%m+b%m)%m,所以只要对每个中间结果也都取余数,就不会有溢出
问题,且不会改变最终输出结果。
代码如下:
循环次数较多的解法:
#include <stdio.h>
#include <string.h>
int f[1000001];
int main()
{
int i, n;
memset(f,0,sizeof(n));
f[0] = f[1] = 1;
for (i = 2; i <= 1000001; i++)
{
if (i % 2)//奇数
{
f[i] = f[i-1];
}
else
{
f[i] = (f[i-1] + f[i/2]) % 1000000000;
}
}
while (scanf("%d", &n) != EOF)
{
if (n > 1000000)
{
printf("%d\n", -1);
}
else
{
printf("%d\n",f[n]);
}
}
return 0;
}
循环次数较少的解法:
#include <iostream>
using namespace std;
int c[1000002];
int main()
{
int n,i;
c[0] = c[1] = 1;
c[2] = c[3] = 2;
for (i = 2; i <= 500000; i++)
{
c[2*i] = (c[2*i - 1] + c[i]) % 1000000000;
c[2*i+1] = c[2*i];
}
while (cin >> n)
{
cout << c[n] << endl;
}
return 0;
}整数分隔,布布扣,bubuko.com
整数分隔
原文:http://blog.csdn.net/lanximu/article/details/20867647