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

题目链接:

http://acm.split.hdu.edu.cn/showproblem.php?pid=4549

题目大意:

已知a,b,n,接下来求解第n项的值。

题目思路:

已知a和b的指数是按照斐波那契数列的顺序进行递增的,所以只要求出a,b的指数即可。

费马小定理:如果p为质数且a,p互质      a^(p-1) = 1(mod  p)

所以 a^n = a^(  n%(p-1) ) * 1 * 1...

A^n%p   这题的p是质素,而且A,p是互质的。
所以直接A^(n%(p-1)) %p
坑点:
在这里矩阵快速幂mod的是p-1所以你在快速幂里写的mod值要为p-1(这个地方没发现,一直傻傻的写着p,wa到死)。
碰到斐波那契要想到矩阵快速幂,遇到质数之类的求膜要想到费马欧拉等定理及引理。
代码:

#include <bits/stdc++.h>
using namespace std;
const int mo = 1000000007;
const int size = 2;
#define ll long long

struct matrix
{
    ll m[size][size];
};

matrix mul(matrix a,matrix b)
{
    matrix c;
    memset(c.m,0,sizeof(c.m));
    for(int i=0;i<size;i++)
    for(int j=0;j<size;j++)
    for(int k=0;k<size;k++) 
    c.m[i][j] = ((a.m[i][k]*b.m[k][j])%(mo-1)+c.m[i][j])%(mo-1);//矩阵快速幂的模要搞清楚 
    
    return c;
} 

matrix quick(matrix a,ll n)
{
    matrix res;
    memset(res.m,0,sizeof(res.m));
    for(int i=0;i<size;i++) res.m[i][i]=1;
    
    while(n){
        if(n&1) res=mul(res,a);
        n>>=1;
        a=mul(a,a); 
    } 
    
    return res;
}

ll quickmo(ll a,ll b,ll p)
{
    ll ans=1;
    ll tmp = a%p;
    while(b){
        if(b&1) ans = ans*tmp%p;
        tmp = tmp*tmp%p;
        b>>=1;
    }
    
    return ans;
}

int main()
{
    matrix p;
    memset(p.m,0,sizeof(p.m));
    p.m[0][1]=p.m[0][0]=p.m[1][0]=1;
    
    ll a,b,n;
    while(~scanf("%lld%lld%lld",&a,&b,&n)){
        if(n==0) printf("%d\n",a);
        else if(n==1) printf("%lld\n",b);
        else if(n==2) printf("%lld\n",a*b%mo);
        else{ 
            matrix ans = quick(p,n-3);
            ll z1 = (ans.m[0][0]*2+ans.m[0][1]*1)%(mo-1);//这里也要满足费马小定理的要求mo-1 
            ll z2 = (ans.m[1][0]*2+ans.m[1][1]*1)%(mo-1);
            
            ll ans1=quickmo(a%mo,z2,mo)%mo;
            ll ans2=quickmo(b%mo,z1,mo)%mo;
            
            printf("%lld\n",ans1*ans2%mo);
        }
    }
 } 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值