题目概括
求第n个斐波那契数。这个n可以很大(10^8)。输出的时候,如果数字不足9位,则输出该数字;否则输出该数字的头四位和尾四位。
思路
参考了这位大佬的输出前四位部分(不是一般的尴尬)https://blog.csdn.net/qq_45034708/article/details/107790982
好吧,先说说前四位。我们可以直接用下面这个公式
感谢百度
怎么用呢?因为当n很大,后面那项直接忽略,前面那项又太大了,所以我们取一个对数(log10),用double存起来。
然后,这个数的小数部分取出来(记为coef)。
最后1000*10^coef,解决问题。
再说后面那四位。由于n太大,所以肯定是矩阵快速幂解决(因为我们有矩阵形式的递推公式)。这里面比较套路。要注意的是,long long 显然是存不下那么大的数字的,所以要取模(我取的是10^9)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2;
const ll inf=1e9;
struct Matrix///不想用指针数组传递二维矩阵就可以这么做
{
ll matrix[maxn][maxn];
Matrix()
{
memset(matrix,0,sizeof(matrix));///好的构造函数
}
};
Matrix mul(Matrix a,Matrix b)
{
Matrix res;
int i,j,k;
for(i=0;i<maxn;i++)
{
for(j=0;j<maxn;j++)
{
for(k=0;k<maxn;k++)
{
res.matrix[i][j]+=a.matrix[i][k]*b.matrix[k][j];
res.matrix[i][j]%=inf;
}
}
}
return res;
}
Matrix quick_mul(Matrix a,int n)
{
Matrix res;
int i;
for(i=0;i<maxn;i++)
{
res.matrix[i][i]=1;
}
while(n)
{
if(n&1) res=mul(res,a);
a=mul(a,a);
n>>=1;
}
return res;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(!n)
{
printf("0\n");continue;
}
if(n==1)
{
printf("1\n");continue;
}
Matrix a;
a.matrix[0][0]=1,a.matrix[0][1]=1,a.matrix[1][0]=1,a.matrix[1][1]=0;
a=quick_mul(a,n-1);
if(n<40) printf("%lld\n",a.matrix[0][0]);
else
{
double coef=log10(1.0/sqrt(5.0))+(double)n*log10((1.0+sqrt(5.0))/2.0);
coef=coef-(int)coef;
printf("%d", (int)(1000.0 * pow(10.0, coef)));///照搬大佬代码
printf("...");
printf("%04d\n",a.matrix[0][0]%10000);
}
}
return 0;
}