蓝桥杯入门训练4——Fibonacci数列

准备蓝桥杯也有一段时间了,今天开始准备把做过的有学到一点东西的题目记录下来,以便日后翻阅。

入门训练 Fibonacci数列

资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

输入格式

输入包含一个整数n。

输出格式

输出一行,包含一个整数,表示Fn除以10007的余数。

样例输入

10
22

样例输出

55
7704

数据规模与约定

1 <= n <= 1,000,000。

刚刚拿到题目的时候没有注意到资源的要求,于是直接写了递归算法提交:

`#include <iostream>
using namespace std;
long F(long n){
	if(n==1 || n==2)
	 return 1;
	else
	 return F(n-1)+F(n-2);
}
int main(){
	long n;
	cin>>n;
	cout<<F(n)%10007<<endl;
}
`

结果当然是运行超时:
递归算法并不适用于这道题目
递归算法在相对较小的范围内还是很实用的,但是在n取到40左右的数字时运行时间就有些长了,一百万的时候就更不用说了。在网络上寻找相关解题方法的时候发现了下面的解法:

#include <iostream>
using namespace std;
int main(){
	int a1=1,a2=1;
	int temp;
	long n;
	cin>>n;
	for(long i=1;i<n;i++){
		temp=a2;
		a2=(a1+a2)%10007;
		a1=temp;
	}
	cout<<a1<<endl;
	return 0;
}

我尝试了很多次去理解这段代码,但是最终也没有完全搞明白。看到有人说其实是使用了余数的加法定理,才稍微有了些头绪。

余数的加法定理:a与b的和除以c的余数,等于a,b分别除以c的余数之和,或这个和除以c的余数。即(a+b)%c=(a%c+b%c)%c。

虽然没搞明白,但是这种方法毫无疑问是接近最佳答案的,它的CPU时间为0ms,内存使用仅为2.449MB。在这里插入图片描述

之后我又想到使用数组来存放每一个Fn%10007的结果,输入n后直接读取也可以解决问题。

#include <iostream>
using namespace std;
long long a[1000000];
void Fibo(){
	a[0]=0;
	a[1]=a[2]=1;
	for(int i=3;i<=1000000;i++){
		a[i]=(a[i-1]+a[i-2])%10007;
	}
}
int main(){
	long n;
	cin>>n;
	Fibo();
	cout<<a[n]<<endl;
	return 0;
}

这种方法的两项指标都比上一种差,但是更容易理解(也许是我太菜了理解不来上一种的原因┭┮﹏┭┮)。

入门训练的四道题目难度都不大,但是确实把需要注意的点都顾及到了,算是基础中的基础吧。

第一次写浪费了太多时间在小细节上,但总算是把做题时的想法都顾及到了。之后遇到值得记录的题目再继续写叭。

发布了7 篇原创文章 · 获赞 0 · 访问量 56

猜你喜欢

转载自blog.csdn.net/qq_21606413/article/details/104520648