bzoj5118: Fib数列2(费马小定理+矩阵快速幂)

  题目大意:求$fib(2^n)$

  就是求fib矩阵的(2^n)次方%p,p是质数,根据费马小定理有

  注意因为模数比较大会爆LL,得写快速乘法...

#include<bits/stdc++.h>
#define ll long long
#define MOD(x) ((x)>=mod?(x-mod):(x))
using namespace std;
const int maxn=500010;
const ll mod=1125899839733759;
struct mtx{ll mp[2][2];mtx(){memset(mp, 0, sizeof(mp));}}ans, base;
ll n, T;
inline ll mul(ll a, ll b, ll mod)
{
    ll ans=0; a%=mod;
    for(;b;b>>=1, a=MOD(a+a))
    if(b&1) ans=MOD(ans+a);
    return ans;
}
mtx operator*(mtx a, mtx b)
{
    mtx c;
    for(int i=0;i<2;i++)
    for(int j=0;j<2;j++)
    for(int k=0;k<2;k++)
    c.mp[i][j]=MOD(c.mp[i][j]+mul(a.mp[i][k], b.mp[k][j], mod));
    return c;
}
inline ll power(ll a, ll b, ll mod)
{
    ll ans=1;
    for(;b;b>>=1, a=mul(a, a, mod))
    if(b&1) ans=mul(ans, a, mod);
    return ans;
}
inline ll mtx_power(ll b)
{
    if(!b) return 0; 
    for(;b;b>>=1, base=base*base)
    if(b&1) ans=ans*base;
    return ans.mp[1][0];
}
int main()
{
    scanf("%lld", &T);
    while(T--)
    {
        scanf("%lld", &n);
        ll t=power(2, n, mod-1);
        base.mp[0][0]=base.mp[0][1]=base.mp[1][0]=1; base.mp[1][1]=0;
        ans.mp[0][0]=ans.mp[1][1]=1; ans.mp[1][0]=ans.mp[0][1]=0;
        printf("%lld
", mtx_power(t));
    }
}
View Code 
原文地址:https://www.cnblogs.com/Sakits/p/8017450.html