簡單的說就是f[n]=f[n-1]+f[n-2],f[1]=1,f[2]=1的一個數列。
1.根據遞推式可以簡單得出一個遞歸求法。
typedef long long ll; ll f(ll x){ if(x==1||x==2)return 1; else return f(x-1)+f(x-2); } int main(){ ll n; scanf("%lld",&n); printf("%lld\n",f(n)); }
2.顯然得出這樣得一個遞歸式子出現了大量得重復計算,可以記憶化優化
typedef long long ll; const int maxn=50; ll f[maxn]; int main(){ ll n; f[1]=f[2]=1; scanf("%lld",&n); for(int i=3;i<=n;i++){ f[i]=f[i-1]+f[i-2]; } printf("%lld\n",f[n]); }
3.如果可以構造如圖所示的矩陣,那么連續給矩陣乘以n個這樣的矩陣就可以得到fn。
又因為矩陣滿足結合律,所以可以用快速冪的方式,除去矩陣乘法的時間復雜度,O(logn)就可以得到斐波那契數列的第n項。
對於常系數線性齊次遞推得到如下結論:
const int N=10,M=10; long long a[10]; long long f[10]; struct matrix{ int n,m; long long a[N][M]; matrix(){// 初始化2*2的單位矩陣 n=m=2; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ a[i][j]=0; } } for(int i=0;i<n;i++){ a[i][i]=1; } } void clear(){ //memset(a,0,sizeof(a)); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ a[i][j]=0; } } } matrix operator+(const matrix &b)const{ matrix tmp; tmp.clear(); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ tmp.a[i][j]=a[i][j]+b.a[i][j]; } } return tmp; } matrix operator*(const matrix &b)const{ matrix tmp; tmp.clear(); for(int i=0;i<n;i++){ for(int j=0;j<b.m;j++){ for(int k=0;k<m;k++){ tmp.a[i][j]=((a[i][k]*b.a[k][j])+tmp.a[i][j]); } } } return tmp; } }; matrix pow2(matrix A,int n){ matrix B; while(n>0){ if(n&1)B=B*A; A=A*A; n/=2; } return B; } long long solve(long long a[],long long f[],int n,int m){ matrix A,B; A.clear(); B.clear(); A.n=B.n=n; A.m=n; B.m=1; for(int i=0;i<n-1;i++){ A.a[i+1][i]=1; } for(int i=0;i<n;i++){ B.a[i][0]=f[n-i-1]; A.a[0][i]=a[n-i-1]; } A=pow2(A,m); B=A*B; return B.a[n-1][0]; } int main(){//求斐波那契數列第m項 a[0]=1,a[1]=1; //系數 f[0]=0,f[1]=1; //前n項 int m; scanf("%d",&m); printf("%lld\n",solve(a,f,2,m)); return 0; }
4.模素數下求類斐波那契數得第n項(2019南昌網絡賽 H. The Nth Item)
題意:Q個詢問,每次求F(N),但是N要用上一次詢問的結果得到,結果mod998244353。
由待定系數法構造等比數列,求得F(n)=1/sqrt(17)*[((3+sqrt(17))/2)^n-((3-sqrt(17))/2)^n]。發現式子中有根號,要做得就是找到一個可以代替根號17得數,也就是17的二次剩余。
例如本題(2019南昌網絡賽 H. The Nth Item)。假設二次剩余為x,那么公式里的全部sqrt(17)都可以換為x。F(n)=1/x*[((3+x)/2)^n-((3-x)/2)^n]。
對於一個數x,求(x^n)%p,顯然可以用歐拉定理降冪為x^(n%phi(p)+phi(p)),本題p=998244353,那么指數n最大便為:1996488703。我們可以分塊預處理,設N=sqrt(1996488703),把X[0]=x^0,X[1]=x^1,...,X[n]=x^N預處理出來,再把pre[0]=x^(0*N),pre[1]=x^(1*N),...,pre[N]=x^(N*N))。
求出來,這樣對於一個詢問n=a*N+b,我們其實就是求 (x^(a*N))*(x^b),即pre[a]*X[b]=pre[n/N]*X[n%N]。
using namespace std; const int N = 5e4; const ll mod = 998244353; const ll inv17 = 438914993;//sqrt(17)的二次剩余 const ll x1 = 736044383;//(3+sqrt(17))/2 const ll x2 = 262199973;//(3-sqrt(17))/2 ll X1[N+10],X2[N+10],pre1[N+10],pre2[N+10]; ll ans,n,q,nn,res; ll mo(ll x){ return x>=mod?x%mod:x; } void Init(){ pre1[0]=pre2[0]=X1[0]=X2[0]=1; for(int i=1;i<=N;i++) X1[i]=mo(X1[i-1]*x1),X2[i]=mo(X2[i-1]*x2); for(int i=1;i<=N;i++) pre1[i]=mo(pre1[i-1]*X1[N]),pre2[i]=mo(pre2[i-1]*X2[N]); } int main(){ Init(); scanf("%lld%lld",&q,&n); res=ans=0; while(q--){ n^=(res*res); nn=n%(mod-1)+mod-1; res=mo(pre1[nn/N]*X1[nn%N])-mo(pre2[nn/N]*X2[nn%N]); res=mo(res+mod); res=mo(res*inv17); ans^=res; } printf("%lld\n",ans); return 0; }
5.斐波那契數列又稱為黃金分割數列
當n趨向於無窮大時,前一項與后一項的比值越來越逼近黃金分割0.618(或者說后一項與前一項的比值小數部分越來越逼近0.618)。
6.斐波那契數與楊輝三角

7.其他公式
奇數項求和:
偶數項求和:
前n項求和:fn+2-1
平方求和: (值得一提的是這個公式也說明了用斐波那契數的前n項為邊長的n個正方形可以構造出一個矩形)
隔項關系:
f(2n-2m-2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n-2m) [ n〉m≥-1,且n≥1]兩倍項關系:f(2n)/f(n)=f(n-1)+f(n+1)
其他公式:
當且僅當,n%4==0時,f[n]%3==0等等。。。。。。