1. 程式人生 > >快速求斐波那契

快速求斐波那契

Description

Fibonacci數列,大家應該都很熟悉了吧? _

Fibonacci數列是這樣定義的:

F[0]=0;

F[1]=1;

F[n]=F[n-1]+F[n-2], for n>1
大家都知道Fibonacci數列的增長速度是驚人的。當n=47時,F[47]=2971215073(>2^31)。由於數列的值增長太快,對於n,你只需要輸出F[n]%12。
Input

第一行,一個整數T(1緊接著有T行,每一行有一個整數n(0<=n<=200000000)

Output

對於每一組測試資料n,輸出一個整數m=F[n]%12。

Sample Input
4
0
1
2
47

Sample Output
0
1
1
1

簡單暴力AC遞推程式碼:

#include<iostream>
using namespace std;
 
int main(){
    int n,f0=0,f1=1,f=0;
    cin>>n;
    for (int i=1;i<=n;i++)
	{
        int a;
        cin>>a;
        if (a==0) cout<<0<<endl;
        else if (a==1) cout<<1<<endl;
        else
        {
        	f0=0,f1=1,f=0;
        	for (int j=2;j<=a;j++)
			{
            	f=(f0%12+f1%12)%12;
            	f0=f1;
            	f1=f;
        	}
        	cout<<f<<endl;
        }
    }
    return 0;
}

優化後的AC遞推程式碼

#include <stdio.h>
using namespace std;
 
int main(){
    int n,f0=0,f1=1;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
	{
        long long a;
        scanf("%lld",&a);
        if (a==0) printf("0\n");
        else if (a==1) printf("1\n");
        else
        {
        	f0=0,f1=1;
        	for (long long j=2;j<a;j+=2)
			{
            	f0=(f0%12+f1%12)%12;
            	f1=(f0%12+f1%12)%12;
        	}
        	if (a%2==0)
			{
				f0=(f0%12+f1%12)%12;
				f1=f0;
			} 
        	printf("%d\n",f1);
        }
    }
    return 0;
}

但還是隻拿80分,如下樣例通不過:
3
199999959
199981533
199993666

最後找了矩陣快速冪方法,連結為:
https://blog.csdn.net/NYIST_TC_LYQ/article/details/52981353
AC程式碼如下:

#include <iostream>
#include <cstddef>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int mod=12;
typedef vector<ll> vec;
typedef vector<vec> mat;
mat mul(mat &a,mat &b)//不太懂 
{
    mat c(a.size(),vec(b[0].size()));
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<2; j++)
        {
            for(int k=0; k<2; k++)
            {
                c[i][j]+=a[i][k]*b[k][j];
                c[i][j]%=mod;
            }
        }
    }
    return c;
}
mat pow(mat a,ll n)
{
    mat res(a.size(),vec(a.size()));
    for(int i=0; i<a.size(); i++)
        res[i][i]=1;//單位矩陣;
    while(n)
    {
        if(n&1) res=mul(res,a);
        a=mul(a,a);
        n/=2;
    }
    return res;
}
ll solve(ll n)
{
    mat a(2,vec(2));
    a[0][0]=1;
    a[0][1]=1;
    a[1][0]=1;
    a[1][1]=0;
    a=pow(a,n);
    return a[0][1];//也可以是a[1][0];
}
int main()
{
    ll n,x;
    cin>>n; 
    for (int i=1;i<=n;i++)
    {
        cin>>x;
		cout<<solve(x)<<endl;
    }
    return 0;
}