洛谷——P1028 数的计算

题目描述

我们要求找出具有下列性质数的个数(包含输入的自然数 n n ):

先输入一个自然数 n n ( n 1000 n\leq1000 ),然后对此自然数按照如下方法进行处理:

  1. 不作任何处理;

  2. 在它的左边加上一个自然数,但该自然数不能超过原数的一半;

  3. 加上数后,继续按此规则进行处理,直到不能再加自然数为止.

输入格式

自然数 n n ,且 n 1000 n\leq1000

输出格式

1个整数,表示具有该性质数的个数

输入输出样例

输入

6

输出

6

扫描二维码关注公众号,回复: 9834914 查看本文章

解释:满足的数分别为6,16,26,126,36,136


1.首次尝试

解法一 递归

显然,最简单直接的做法就是递归(将一个大问题规约成更小规模的子问题,通过子问题的求解完成原问题)
假设:
当输入为4时,满足的其性质的数有——4本身,加上其规模 1 / 2 ^1/_2 的子问题解的个数,即 4, 24, 124
根据我们的分析,算法的也就不难写出来了,递归代码如下

int fun(int n) {	//版本一 递归
	int cnt = 0;
	for(int i=1; i<=n/2; i++) {
		cnt += fun(i);
	}
	return cnt+1;
}

2.超时

递归的方法虽然简单直观,但是提交没过——超时了,递归深度太深导致爆栈了,这时候我们就需要思考能不能改进?能不能进一步优化?

启发

还记得最初在学习递归的时候,一个经典的案例就是斐波那契数列 f ( n ) = f ( n 1 ) + f ( n 2 ) , n 2 f(n) = f(n-1) + f(n-2), n\geq2
我们发现,当递归调用的时候,其中某一个子树的值可能会被重复计算很多次,很费时间:
图片摘自网络,侵删
例如图中 f ( 2 ) f(2) 的值就被重复计算了三次,那么我们能不能让它只计算一次呢?

动态规划(DP)思想

对于斐波那契数列的一种优化方法就是利用数组暂存中间值,这样就避免了重复计算
那么什么又是动态规划?

遵循动态规划算法是将问题递归地分解成更简单的重叠子问题,通过子问题的解决来解决原问题
动态规划目前已广泛应用于经济学、计算机视觉、语音识别、人工智能、计算机图形学和生物信息学

在斐波那契数列的例子中,多次计算的 f 2 f(2) 的值,这样就是一个重叠的子问题,我们应避免重复计算带来的时间开销,于是引入了数组——保存每一次计算的值(这样一个过程称为记忆, 对于提高递归算法效率是很重要的技术)

3.优化

我们有了思路,下面的关注点就在于寻找该问题的一个递推关系式
我们先列出来一部分:(其中 f ( n ) f(n) 表示自然数 n n 所具有上述三种性质的个数)

f ( 1 ) = 1 f(1) = 1
f ( 2 ) = 2 f(2) = 2 f ( 3 ) = 2 f(3) = 2
f ( 4 ) = 4 f(4) = 4 f ( 5 ) = 4 f(5) = 4
f ( 6 ) = 6 f(6) = 6 f ( 7 ) = 6 f(7) = 6
f ( 8 ) = 10 f(8) = 10 f ( 9 ) = 10 f(9) = 10

我们可以看出:

  • n n 为奇数时( n > 1 n>1 ), f ( n ) = f ( n 1 ) f(n) = f(n-1)

  • n n 为偶数时,分析却复杂一些,我们不妨画出其递归树结构:
    在这里插入图片描述
    f ( 4 ) f(4) 为例,观察其结构,我们发现右框部分就是 f ( 4 / 2 ) f(4/2) 的个数,那么左边是什么呢?
    仔细思考左框可以看出,左部分的个数相当于少了一个 f ( 4 / 2 ) f(4/2) 子树的个数,这不正好等于 f ( 3 ) f(3) 吗?

综上,我们可以得出递推式:

  1. f ( 1 ) = 1 f(1) = 1
  2. n > 1 n>1
    • n n 为奇数, f ( n ) = f ( n 1 ) f(n) = f(n-1)
    • n n 为偶数, f ( n ) = f ( n 1 ) + f ( n / 2 ) f(n) = f(n-1) + f(n/2)

代码

long fun(int n){
	long a[n+1];

	a[0] = 1;
	
	for(int i=1; i<n+1; i++){
		if(i%2 != 0)    //奇数
			a[i] = a[i-1];
		else
			a[i] = a[i-1] + a[i/2];
	}
	
	return a[n];
}

4.小结

学习算法的道路漫长且艰巨,唯有不断打磨自己不断思考,挖掘其背后的本质,才能取得进步

发布了5 篇原创文章 · 获赞 1 · 访问量 119

猜你喜欢

转载自blog.csdn.net/Apol1o_/article/details/104878295
今日推荐