题目描述
我们要求找出具有下列性质数的个数(包含输入的自然数n):
先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理:
不作任何处理;
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
加上数后,继续按此规则进行处理,直到不能再加自然数为止.
输入格式
1个自然数n(n≤1000)
输出格式
1个整数,表示具有该性质数的个数。
输入输出样例 6 6
满足的数 6,16,26,126,36,136
这个题常规来想其实并不难,这是一个很简单的暴力递归
但题目要求是在1000之内, 暴力递归就会超时了
所以需要优化代码,这里采取记忆的方法(本人蒟蒻,请蒟蒻不要看到记忆二字退出)
#include <stdio.h>
#include <stdlib.h>
int f[1002]={0}; //定义全局数组并赋值为零,用来判断在递归的过程中有没有曾计算过的值 解释1:
int num(int n)
{
f[1]=1;
int i,sum=1; //本身也可以所以sum从1开始
if(n==1)
{
return f[n];
}
else
{
if(f[n]==0) //判断曾经有没有出现过
{
for(i=1;i<=n/2;i++)
{
sum+=num(i);
}
return f[n]=sum; //解释二:
}
else
{
return f[n];
}
}
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",num(n));
return 0;
}
解释1;例如在计算num(4)时,会调用num(2),这样如果重复递归很麻烦,如果num(2)在此前出现过,则将它记录下来,这样可以大大减少计算量。
解释2:注意这里面每次返回的都是f(n),f(n)无论怎样都曾经有过sum为其赋值。
关于递归,可能有些小伙伴不理解他是怎样运作的东西,你们其实可以用中文解释来思考,你们定义的函数究竟是一个干什么的函数,例如此题中的num函数,你要知道这个函数的作用是什么。num函数是一个求出输入n前面有多少种成立情况的函数,每次你遇到他时你就可以这么想他。
如果不能完全理解上面这段话,可以参照汉诺塔问题,在打印方法时,用的是同一种思想。
版权声明:本文为Nanrdml原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。