# 【bzoj5118】Fib数列2 费马小定理+矩阵乘法

Fib定义为Fib(0)=0,Fib(1)=1,对于n≥2,Fib(n)=Fib(n-1)+Fib(n-2)

n≤10^15, T≤5

2
2
31

3
343812777493853

#include <cstdio>
#include <cstring>
#define mod 1125899839733759
typedef long long ll;
inline ll mul(ll x , ll y , ll p)
{
ll ans = 0;
while(y)
{
if(y & 1) ans = (ans + x) % p;
x = (x + x) % p , y >>= 1;
}
return ans;
}
inline ll pow(ll x , ll y , ll p)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = mul(ans , x , p);
x = mul(x , x , p) , y >>= 1;
}
return ans;
}
struct data
{
ll v[2][2];
data() {memset(v , 0 , sizeof(v));}
ll *operator[](int a) {return v[a];}
data operator*(data a)
{
data ans;
int i , j , k;
for(i = 0 ; i < 2 ; i ++ )
for(k = 0 ; k < 2 ; k ++ )
for(j = 0 ; j < 2 ; j ++ )
ans[i][j] = (ans[i][j] + mul(v[i][k] , a[k][j] , mod)) % mod;
return ans;
}
data operator^(ll y)
{
data x = *this , ans;
ans[0][0] = ans[1][1] = 1;
while(y)
{
if(y & 1) ans = ans * x;
x = x * x , y >>= 1;
}
return ans;
}
}A;
int main()
{
int T;
scanf("%d" , &T);
while(T -- )
{
ll n;
scanf("%lld" , &n) , n = pow(2 , n , mod - 1);
A[0][0] = 0 , A[0][1] = A[1][0] = A[1][1] = 1 , A = A ^ n;
printf("%lld\n" , A[1][0]);
}
return 0;
}


posted @ 2018-04-03 20:49  GXZlegend  阅读(600)  评论(0编辑  收藏