整数分隔

描述:
一个整数可以拆分为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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值