牛客42659857 The GCD of Fibonacci Numbers解题报告

假期第一天,当然是好好学习啦。今天去牛客网上一玩,果不其然的。。自闭了。。算了,自闭了也要有所收获吧。分享一道数论题,有点意思,涉及到很多东西,弄懂的话能学到很多。

题目描述

链接:https://ac.nowcoder.com/acm/problem/200091
大概意思:f表示斐波那契数列(定义f0=0,f1=1,f2=1…)。输入两个数m,n,求出fm,fn的最大公因数。

思路分析

看到题目,第一眼应该感觉很简单。动笔之前,看了一眼数据范围:1 ≤m,n ≤ 2^31。。。我人傻了??这样只是暴力的话肯定是做不出来的。
于是,思考了良久,并在大佬的帮助下,找到了几个数学方面的知识点:
1、斐波那契数和项数之间的关系:gcd(f(m),f(n))==f(gcd(m,nn));
大佬博客:https://blog.csdn.net/alan_cty/article/details/73928751
2、斐波那契数列和矩阵之间的关系:
大佬博客:https://blog.csdn.net/qq_41286356/article/details/89437065
有了这两个工具,相信思路就不复杂了:首先,利用第一个数学关系,得出所要求的斐波那契数的项数(这里提示下,stl含有__gcd()函数,直接求出最大公约数),之后,再用快速幂得出斐波那契数。在此之前,可以定义一个表示矩阵的结构体,然后重载一下*运算符,这样后续操作或许能简单一些。(当然,直接定函数或者其他手法也行,总体思路一样就好)。通过这道题确实收获良多,希望对各位有所帮助。

完整代码

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int mod=1e8;
struct mat{
    ll a[15][15];
    mat(){
        memset(a,0,sizeof(a));
    }
    mat operator*(mat b){
        mat ans;
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                for(int k=0;k<2;k++)
                {
                    ans.a[i][j]+=(a[i][k]*b.a[k][j]);
                }
            }
        }
        return ans;
    }
};
ll fun(ll i)
{
    mat bas;
    mat res;
    for(int j=0;j<2;j++) res.a[j][j]=1;
    bas.a[0][0]=bas.a[0][1]=bas.a[1][0]=1;
    bas.a[1][1]=0;
    while(i--) res=res*bas;
    return res.a[0][1];
}
 
 
int main()
{
    ll n,m;
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%lld %lld",&n,&m);
        if(n<m) swap(n,m);
        printf("%lld\n",fun(__gcd(n,m)));
    }
    return 0;
}

最后,祝大家假期愉快~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值