笨人小白的温故知新——递归(4)

1202:Pell数列

其实本来是一段很简单的代码,但是这个题带给我的收获很大,所以我决定来做一个自己的反思回顾。

来讲一下我做这道题遇到的问题(主要是解决运行超时的问题):

1)我一开始并没有用记忆化,导致运行超时。

2)我用了一个记忆化(但是是错的)

long long pell(int k){
	if(!pell(k))	return ;
}

现在,我已经知道了我的错因:!pell(k) 试图判断返回值是否为 0,但 pell(k) 本身又会无限递归,永远无法执行到后续逻辑;

3)然后我做了如下改动:

const int MOD = 32767 , N = 1e6+10;
long long a[N] ;
long long pell(int k){
	if(a[k] != 0)	return a[k] ;
	if(k == 1)	return 1 ;
	if(k == 2)	return 2 ;
	a[k] = (2*pell(k-1) + pell(k-2))%MOD ;
	return a[k] ;
}

这样,就获得了一个AC代码:

#include <iostream>
#include <stdio.h>
using namespace std ;
const int MOD = 32767 , N = 1e6+10;
long long a[N] ;
long long pell(int k){
	if(a[k] != 0)	return a[k] ;
	if(k == 1)	return 1 ;
	if(k == 2)	return 2 ;
	a[k] = (2*pell(k-1) + pell(k-2))%MOD ;
	return a[k] ;
}
int main()
{
	int n , s ; scanf("%d" , &n) ;
	while(n--){
		scanf("%d" , &s) ;
		printf("%lld\n" , pell(s)) ;
	}
	return 0;
}

你以为这就结束了?NO~~~ 好奇的我,又换了一种:

a[k] = 2*pell(k-1)%MOD + pell(k-2)%MOD ;

但是却运行超时了。why?

笨笨的我问了豆包,豆包说:

“取模是「相对耗时」的操作

取模(%)本质是除法 + 求余,属于 CPU 的复杂指令(比加法 / 乘法慢得多)。前者只执行 1 次取模,后者执行 2 次,仅这一步就会产生「指令数翻倍」的开销 —— 尤其是在循环 / 递归的高频调用场景下(比如计算 pell (1e5)),两次取模的累计耗时会被放大,最终体现为「后者更慢」。”

今天也回顾了好几道题,但是都比较简单,所以没有写到我的博客里。(嘻嘻

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值