1. 程式人生 > >51NOD 1358 浮波那契 【矩陣快速冪】

51NOD 1358 浮波那契 【矩陣快速冪】

1358 浮波那契
基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級演算法題

TengBieBie已經學習了很多關於斐波那切數列的性質,所以他感到一些些厭煩。現在他遇到了一個新的數列,這個數列叫做Float-Bonacci。這裡有一個關於Float-Bonacci的定義。


對於一個具體的n,TengBieBie想要快速計算FB(n).

但是TengBieBie對FB的瞭解非常少,所以他向你求助。

你的任務是計算FB(n).FB(n)可能非常大,請輸出FB(n)%1,000,000,007 (1e9+7)即可。
Input

輸入共一行,在一行中給出一個整數n (1<=n<=1
,000,000,000)。 Output 對於每一個n,在一行中輸出FB(n)%1,000,000,007 (1e9+7)。 Input示例 5 Output示例 2 System Message (題目提供者)

比較裸的矩陣快速冪問題 (這樣也4級…)

n=n10
F(n)=F(n10)+F(n34)
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x)) using namespace std; const int inf = 1e9+7; const int N = 1e4+7; struct Matrix { const static int sz = 34; ll mat[sz][sz]; Matrix(bool E = false){ MEM(mat,0); if(E){ for(int i=0;i<sz;++i){ mat[i][i]=1; } } } ll* operator
[](const int idx){ return mat[idx]; } const ll* operator [](const int idx)const{ return mat[idx]; } Matrix operator*(const Matrix&other){ Matrix ans; for(int i=0;i<sz;++i){ for(int j=0;j<sz;++j){ ans[i][j]=0; for(int k=0;k<sz;++k){ ans[i][j]+=mat[i][k]*other[k][j]; ans[i][j]%=inf; } } } return ans; } Matrix operator^(ll n){ Matrix ans(true); Matrix tmp = *this; while(n>0){ if(n&1){ ans = ans*tmp; } tmp = tmp*tmp; n>>=1; } return ans; } }; Matrix m; void init(){ m[0][9]=m[0][33]=1; for(int i=1;i<34;++i){ m[i][i-1]=1; } } ll slove(ll n){ if(n<41){ return 1; } Matrix t = m^(n-40); ll ans = 0; for(int i = 0; i < 34; ++i){ ans += t[0][i]; ans %= inf; } return ans; } int main(){ //freopen("/home/lu/code/r.txt","r",stdin); //freopen("/home/lu/code/w.txt","w",stdout); ll n; init(); while(~scanf("%lld",&n)){ n*=10; printf("%lld\n",slove(n)); } return 0; }