题目表示的很明确,要用两个算法,斐波那契数列是很经典的dp问题,最大公约数是很经典的辗转相除法,从而我理所应当的就定义一个数组存放斐波那契数列:
long long int F[2021]={0};
F[1]=1;
F[2]=1;
for(int i=3;i<2021;i++)
{
F[i]=F[i-1]+F[i-2];
}
自定义一个辗转相除法的函数来计算最大公约数:
long long int gcd(long long int A,long long int B)
{
long long int temp;
while(B!=0)
{
temp=A%B;
A=B;
B=temp;
}
return A;
}
因为考虑到了斐波那契数列到F[2020]的时候肯定会超过小小的int的范围,而特地使用了long long int,却还是意料之外又情理之中的爆了,输出结果是-1。
当我在想使用大数加法那样用数组当数字使用的时候,我搜了一下斐波那契数列与最大公约数的关系,发现了这个:
gcd(F(m),F(n))=F(gcd(m,n))
又称之为:
斐波那契数列的最大公约数定理
此时的我才反应过来,这样就不怕数据爆了:
int F[2021]={0};
F[1]=1;
F[2]=1;
int i;
for(i=3;i<=gcd(2020,520);i++)
{
F[i]=F[i-1]+F[i-2];
}
甚至都没有超过int的范围。
上代码:
#include <bits/stdc++.h>
using namespace std;
int gcd(int A,int B)
{
int temp;
while(B!=0)
{
temp=A%B;
A=B;
B=temp;
}
return A;
}
int main()
{
int F[2021]={0};
F[1]=1;
F[2]=1;
int i;
for(i=3;i<=gcd(2020,520);i++)
{
F[i]=F[i-1]+F[i-2];
}
cout << F[i-1];//i在上面结束循环的时候多自加一次,所以要减去
return 0;
}
觉得求最大公约数的时候代码太长显得冗杂,也可以用递归的方式:
int GCD(int a,int b)
{
if(a%b!=0)
return GCD(b,a%b);
else
return b;
}
使用递归还是循环,还是取决于时间复杂度,递归需要的时间比循环长,但是经过指点,发现个更nb的方法:
int gcd(int a, int b)
{
return b? gcd(b, a%b) : a;
}