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

题目链接https://vjudge.net/contest/347398#problem/G
在这里插入图片描述
分析
1.如何构建矩阵和斐波那契数列联系起来。
f[0]=a
f[1]=b
f[2]=ab
f[3]=ab^2
f[4]=a^2 b^3
f[5]=a^3 b^5
f[6]=a^5 b^8

由此可见a和b的系数和斐波那契数列有联系

构造矩阵
1 1
1 0
加上单位矩阵
1 0
0 1

用矩阵快速幂表示出斐波那契的第n项的值。
此题结果对1e9+7取余,考虑1e9+7为素数
在求解a和b系数的过程,引入费马小定理进行优化
费马小定理
若p为素数,gcd(a,p)=1,则a^(p-1)=1(mod p)
推广:p为素数,x^p-x(x为任意正整数)必定能被p整除(相当于1从右边移到左边,没有余数了)
费马小定理的降幂处理
a^b mod p若符合费马小定理的使用条件,则
a^b mod p=a^ (b%(p-1)) mod p
b转化为p-1的整数倍+余数。因为a^(p-1) mod p=1,所以可以达到降幂处理的效果。

a p不互质:
a^b进行降幂处理:
a^b=a ^b(mod n) b<phi(n)
a^b=a ^(b%phi(n)+phi(n))(mod n) b>=phi(n)
phi(n) 为n的欧拉函数

代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=1000000007;
struct node
{
    LL m[3][3];
} first,second;
node update(node x,node y)
{
    node temp;
    for(int i=1; i<=2; i++)
    {
        for(int j=1; j<=2; j++)
        {
            temp.m[i][j]=0;
            for(int k=1; k<=2; k++)
            {
                temp.m[i][j]+=x.m[i][k]*y.m[k][j];
                temp.m[i][j]%=(mod-1);
            }
        }
    }
    return temp;
}
void Quick_Mi(LL res)
{
    for(int i=1; i<=2; i++)
        for(int j=1; j<=2; j++)
        {
            if(i==j)
                first.m[i][j]=1;
            else
                first.m[i][j]=0;
        }
    second.m[1][1]=1;
    second.m[1][2]=1;
    second.m[2][1]=1;
    second.m[2][2]=0;
    while(res)
    {
        if(res&1)
            first=update(first,second);
        second=update(second,second);
        res>>=1;
    }
}
LL solve(LL num,LL res)
{
    LL sum=1;
    while(res)
    {
        if(res&1)
            sum=(sum*num)%mod;
        num=(num*num)%mod;
        res>>=1;
    }
    return sum;
}
int main()
{
    LL a,b,n;
    while(~scanf("%lld%lld%lld",&a,&b,&n))
    {
        if(n==0)
        {
            cout<<a<<endl;
            continue;
        }
        if(n==1)
        {
            cout<<b<<endl;
            continue;
        }
        if(a==0||b==0)
        {
            cout<<0<<endl;
            continue;
        }
        Quick_Mi(n);/*快速幂求其系数*/
        LL fb=first.m[1][2]%(mod-1);/*a和b的系数在其矩阵中表示的位置*/
        LL fa=first.m[2][2]%(mod-1);
        LL t1=solve(b,fb);
        LL t2=solve(a,fa);
        LL tail=t1*t2%mod;
        cout<<tail<<endl;
    }
    return 0;
}

在这里插入图片描述

发布了165 篇原创文章 · 获赞 6 · 访问量 5052

猜你喜欢

转载自blog.csdn.net/lylzsx20172018/article/details/103478748
今日推荐