码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-12-10 17:38:02      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:body   max   lin   str   题目   ret   text   alt   play   

  题目大意:求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(费马小定理+矩阵快速幂)

标签:body   max   lin   str   题目   ret   text   alt   play   

原文地址:http://www.cnblogs.com/Sakits/p/8017450.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!