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

Posted Sakits

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n", mtx_power(t));
    }
}
View Code 

以上是关于bzoj5118: Fib数列2(费马小定理+矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj5118Fib数列2 费马小定理+矩阵乘法

BZOJ_5118_Fib数列2_矩阵乘法+欧拉定理

费马小定理+矩阵快速幂HDU4549——M斐波那契数列

HDU 4549 M斐波那契数列(矩阵快速幂&费马小定理)

HDU4549 M斐波那契数列(矩阵快速幂+费马小定理)

HDU 4549 M斐波那契数列(矩阵快速幂 费马小定理)