BZOJ_5118_Fib數列2_矩陣乘法+歐拉定理
阿新 • • 發佈:2018-05-20
-s names () 接下來 ret ++ algo urn AI
2
31Sample Output
3
343812777493853
根據歐拉定理,有$a^{n}modp=a^{nmod\varphi(p)}modp$。 然後矩陣乘法即可。需要用到快速乘 代碼:
BZOJ_5118_Fib數列2_矩陣乘法+歐拉定理
Description
Fib定義為Fib(0)=0,Fib(1)=1,對於n≥2,Fib(n)=Fib(n-1)+Fib(n-2) 現給出N,求Fib(2^n).Input
本題有多組數據。第一行一個整數T,表示數據組數。 接下來T行每行一個整數N,含義如題目所示。 n≤10^15, T≤5Output
輸出共T行,每行一個整數為所求答案。 由於答案可能過大,請將答案mod 1125899839733759後輸出Sample Input
22
31
Sample Output
3343812777493853
根據歐拉定理,有$a^{n}modp=a^{nmod\varphi(p)}modp$。 然後矩陣乘法即可。需要用到快速乘 代碼:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef long long ll; const ll p=1125899839733759ll; ll n; ll qc(ll x,ll y,ll mod) { ll re=0; for(;y;y>>=1ll,x=(x+x)%mod) if(y&1ll) re=(re+x)%mod; return re; } ll qp(ll x,ll y,ll mod) { ll re=1; for(;y;y>>=1ll,x=qc(x,x,mod)) if(y&1ll) re=qc(re,x,mod); return re; } struct Mat { ll v[2][2]; Mat() {memset(v,0,sizeof(v));} Mat operator * (const Mat &x) const { Mat re; int i,j,k; for(i=0;i<2;i++) { for(j=0;j<2;j++) { for(k=0;k<2;k++) { (re.v[i][j]+=qc(v[i][k],x.v[k][j],p))%=p; } } } return re; } }; Mat pow(Mat &x,ll y) { Mat I; I.v[0][0]=I.v[1][1]=1; while(y) { if(y&1ll) I=I*x; x=x*x; y>>=1ll; } return I; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%lld",&n); n=qp(2,n,p-1); Mat x; x.v[0][1]=x.v[1][0]=x.v[1][1]=1; Mat T=pow(x,n); printf("%lld\n",T.v[1][0]); } }
BZOJ_5118_Fib數列2_矩陣乘法+歐拉定理