大意:
8位及以下的fib直接输出,8位以上的输出XXXX(fib前四位)...XXXX(fib后四位)。
思路:
8位以下的打表输出就好了。
fib的前四位可以利用通项公式fn=1/√5/*[(1+√5)^n/2)-(1-√5)^n/2]来求,利用对数知识求解。
例如:
log(2335566)=log(2.335566)+2.
那么log(2.335566)是log(2335566)的小数部分。
然后将log(2.335566)变为10的指数,
那么前四位就是所得的数在<10000时x10所得数的整数部分。
fib的后四位有两种求法,一是循环找出后四位的规律得到循环解,二是通过变换矩阵((1,1),(1,0))+矩阵快速幂求解。
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
using namespace std;
struct matrix
{
int a[11][11];
void clear()
{
memset(a,0,sizeof(a));
}
void clear1()
{
for(int i=0; i<11; i++)
a[i][i]=1;
}
void zhuanzhi()
{
a[0][0]=1;
a[0][1]=1;
a[1][0]=1;
a[1][1]=0;
}
} danw,zhuan;
matrix mul(matrix a,matrix b,int n,int mod)
{
matrix ans;
ans.clear();
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
for(int k=0; k<n; k++)
{
ans.a[i][j]+=(a.a[i][k]%mod*b.a[k][j]%mod)%mod;
ans.a[i][j]%=mod;
}
}
//ans.n=n;
return ans;
}
matrix Qmod(int k,matrix a,int mod,int n)
{
matrix ans=danw;
while(k)
{
if(k&1)
ans=mul(ans,a,n,mod);
k>>=1;
a=mul(a,a,n,mod);
}
return ans;
}
int main()
{
const double geng5=sqrt(5);
int a[40];
a[0]=0,a[1]=1;
zhuan.zhuanzhi();
danw.clear1();
for(int i=2;i<40;i++)
{
a[i]=a[i-1]+a[i-2];
//cout<<a[i]<<" "<<i<<endl;
}
int n;
while(cin>>n)
{
if(n<=39)
cout<<a[n]<<endl;
else
{
double b=log10(1/geng5)+(double)n*log10((1+geng5)/2);
b=b-floor(b);
b=pow(10,b);
while(b<1000)
b*=10;
matrix ans=Qmod(n,zhuan,10000,2);
printf("%d...%04d\n",(int)b,ans.a[1][0]);
}
}
return 0;
}