快速求斐波那契
阿新 • • 發佈:2018-11-11
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;
}