整数分解为2的幂(递归)C语言

来源:互联网 发布:安娜baby淘宝店 编辑:程序博客网 时间:2024/06/16 04:49

最近遇到这样的一道题,用到了递归,采用两种办法实现,第一种超时,第二种满足要求。算法小白也算是递归有了一个初探。题目如下:

一个正整数可以表示为多个正整数相加的表达式,表达式中的各个正整数要求都是2的幂。例如给定正整数7,它有下列六个符合要求的表达式:
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
因此,正整数7符合条件的表达式个数是6. 编写一个程序,对于给定的正整数N(1 <= N <= 1,000),输出符合条件的表达式个数。要求:时间复杂度不高于O(N)。

起初没有思路,参考http://blog.csdn.net/zhang20072844/article/details/17033931 用C写了两种方法。


一、递推公式

    我们可以先分析如下几个例子:

1的分解方法 有1种

   1

2的分解方法 有2种

   1 +1

   2

3的分解方法 有2种

   1+1+1

   1+2

4的分解方法 有4种

   1+1+1+1

   1+1+2

   2+2

   4

5的分解方法有 4种

  1+1+1+1+1

  1+1+1+2

  1+2+2

  1+4

6的分解方法有 6种

  1+1+1+1+1+1

  1+1+1+1+2

  1+1+2+2

  1+1+4

  2+2+2

  2+4

7的分解方法有6种

 1+1+1+1+1+1+1 
 1+1+1+1+1+2 
 1+1+1+2+2 
 1+1+1+4 
 1+2+2+2 
 1+2+4

 列举的上述几个我们不难发现这样几个规律

对于任意一个奇数n(除1之外)都和他前面一个的偶数n-1的分解方案相等


对于任意一个偶数(n)都等于他前面的一个奇数(n-1)的分解方案数加上(n/2)方案的数


那么由此可以得出我们的递归公式

n位1时:f(n)

n为奇数时f(n)=f(n-1);

n为偶数是f(n)=f(n-1)+f(n/2);

二、方法一

根据递归公式我们很容易写出递归函数

#include<stdio.h>
#include<stdlib.h>
int f(int n)
{
if (n == 1)
return 1;
else if (n % 2 == 1)
return f(n-1);
else
return f(n - 1)+f(n/2);
}
int main()
{
int a,m;
while (scanf("%d",&a)==1)
{
m = f(a);
printf("%d\n", m);
}
    return 0;
}

但是利用这种方法会超时,这是因为,你计算f(100)的时候层层递归,f(10)会被算很多次。这样数越大,算的越多,很浪费。因此有了下一种方法。

二、方法二

我们利用一个数组,从1到n的分解数都存在一个数组中,用到的时候直接调用,这样就不会超时啦啦啦啦

#include<stdio.h>
#include<stdlib.h>

int main()
{
int a,i;
int m [10001] ;
while (scanf("%d",&a)==1)
{
m[1] = 1;
for (i = 2; i <= a; i++)
{
if (i % 2 == 0)
{
m[i] = m[i - 1]+m[ i / 2];
}
else 
{
m[i] = m[i - 1];
}
}
printf("%d\n", m[a]);
}
    return 0;
}

原创粉丝点击