递推与递归

在刷题的过程中刷到了两道既能用递归来做,也能用递推来做的题目,但是每道题目都有时间和空间的限制,递推和递归并无明显的优劣,要结合题目要求具体分析,有时候用递推更快,无法用递归;有时用递归更快,无法用递推。

题目1:扩充序列

给定一个只包含一个数字 1 的序列 [1]。

现在,要对该序列进行 n−1 次扩充。

每次扩充时,首先要将序列本身添加到其自身的尾部,然后还要在两个序列中间插入还未使用过的最小正整数。

例如,序列 [1] 经过一次扩充后,得到序列 [1,2,1],再经过一次扩充后,得到序列 [1,2,1,3,1,2,1]。

现在,请你计算在经过 n−1 次扩充后,序列的第 k 个元素的值是多少?(元素从 1 开始编号)

输入格式
共一行,包含两个整数 n 和 k。

输出格式
输出一个整数,表示经过 n−1 次扩充后,序列的第 k 个元素的值。

数据范围
对于前三个测试点,1≤n,k≤10。
对于全部测试点,1≤n≤50,1≤k≤2n−1。

输入样例1:
3 2
输出样例1:
2
输入样例2:
4 8
输出样例2:
4
样例解释
对于样例 1,经过 2 次扩充,得到序列 [1,2,1,3,1,2,1],其第 2 个元素为 2。

对于样例 2,经过 3 次扩充,得到序列 [1,2,1,3,1,2,1,4,1,2,1,3,1,2,1],其第 8 个元素为 4。

#利用递推来做超时,因为扩充后的list太大了,导致list之间的加法复杂度太高,报错MemoryError
# n,k = map(int, input().split())

# x = [1]
# num = [2]

# for i in range(0,n):
#     x = x + num
#     x = x + x[0:-1]
#     num[0] = num[0] + 1
# print(x[k-1])



# 只能用递归来做,自顶向下的思考,递归的次数最多只有50次,而且不需要保存列表
def f(n,k):
    part = 2**(n-1) -1 
    if k == part + 1:
        return n;
    elif k <= part:
        return f(n-1,k)
    else:
        return f(n-1, k-part-1)

n,k = map(int, input().split())
print(f(n,k))

题目2:递推数列

给定 a0,a1,以及 an=p×an−1+q×an−2 中的 p,q。

这里 n≥2。

求第 k 个数 ak 对 10000 的模。

输入格式
输入包括 5 个整数:a0、a1、p、q、k。

输出格式
第 k 个数 ak 对 10000 的模。

数据范围
1≤a0,a1,p,q,k≤10000
输入样例:
20 1 1 14 5
输出样例:
8359

# 递归做会超时,因为递归的次数太多了,比如k若=9999,需要递归9999次

a0,a1,p,q,k =  map(int, input().split())
# 提前对10000取模的目的是减少计算量,变成10000以下的数进行计算,根据数学性质,先取模和最后取模不影响结果
a0 = a0 % 10000
a1 = a1 % 10000
p = p % 10000
q = q % 10000

def f(x):
    if x == 0:
        return a0 
    elif x == 1:
        return a1 
    else:
        return (p*f(x-1) + q*f(x-2)) 
    
res = f(k)

print(res)

# 只能用递推做,对于这个题来说,递推只是一个数组,所以用递推做更快,不会超时
# a0,a1,p,q,k =  map(int, input().split())

# a = [0 for i in range(k + 1)]
# a[0] = a0 %10000
# a[1] = a1 %10000

# for k in range(2,k+1):
#     a[k] = p*a[k-1] + q*a[k-2]
# print(a[k]%10000)
 


  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ming__chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值