• gcd步数


    题目描述

    一个有趣的函数F(a,b),表示对于数对(a,b)调用辗转相除法的步数为多少

    例如 (24,40)....0 (16,24).....1 (8,16).....2 (0,8)....3,即f(24,40)=3

    现在已知f(a,b)=k,求(a,b)使得a+b尽量小,同时,由于最终的(a,b)可能比较大,所以你只要在模10^9+7同余系下输出结果即可

    输入输出格式

    输入格式:

    一个数k

    输出格式:

    两个数a,b

    输入输出样例

    输入样例#1:
    1000000007
    输出样例#1:
    0 1000000006

    说明

    对于100% 数据 k < 10^15

    这个题很有意思,值得一想 

    我们需要考虑gcd的过程 

    最差情况是 -> 每次操作都是商1 -> 相当于两个数做差 

    这个时候就是次数最多,也就是我们要找的最小的a,b的情况

    由反复做差 -> 可以联想到斐波那契数列

    经过简单的举例, 

    这个题就是求斐波那契数列的第 k和k+1 项

    (上面不太懂的话自己举个例推算一下就很好理解了)

    由于数据范围很大,所以需要拿矩阵快速幂来算

    代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define MAXN 110
    #define mod 1000000007
    using namespace std;
    long long N,M;
    struct Matrix{
        long long mat[MAXN][MAXN];
        
        Matrix operator *(const Matrix& a)
        {
            Matrix c;
            memset(c.mat,0,sizeof c.mat);
            for(int i=1;i<=N;i++)
                for(int j=1;j<=N;j++)
                    for(int k=1;k<=N;k++)
                        c.mat[i][j]=(c.mat[i][j]+mat[i][k]*a.mat[k][j])%mod;
            return c;
        };
        
        Matrix operator ^(long long k)
        {
            Matrix c=*this,t=*this;
            k--;
            for(;k;k>>=1,t=t*t)
                if(k&1)c=c*t;
            return c;
        };
        
        void print()
        {
            for(int i=1;i<=N;i++)
            {
                for(int j=1;j<=N;j++)printf("%d ",mat[i][j]);
                printf("
    ");
            }
        };
        void scan()
        {
            for(int i=1;i<=N;i++)
                for(int j=1;j<=N;j++)
                    scanf("%lld",&mat[i][j]);
        };
    };
    
    int main()
    {
        scanf("%lld",&M);M++;
        if(M==2){printf("1 1
    ");return 0;}
        if(M>2)M-=1;
        else {printf("1");return 0;}
        Matrix x;
        N=2,x.mat[1][1]=1,x.mat[1][2]=1,x.mat[2][1]=1,x.mat[2][2]=0;
        Matrix p=x^M;
        printf("%lld ",p.mat[1][1]);
        p=x*p;
        printf("%lld
    ",p.mat[1][1]);
        return 0;
    }
  • 相关阅读:
    tfs2012服务器搭建报表、门户、TFS权限设置
    遥望星空FTP文件同步工具(附源码)1.0 发布
    TortoiseGit连接gitlab,一直要求输入密码
    static、const、readonly与static readonly的区别与联系
    sql server对并发的处理乐观锁和悲观锁
    asp.net控件开发基础系列
    Sonne的健身日志(15)16周腹肌计划第四周感受
    上海新闻!
    Sonne的健身日志(9)16周腹肌计划第一周(2012.3.92012.3.15)
    Sonne的健身日志(5)
  • 原文地址:https://www.cnblogs.com/Elfish/p/7695113.html
Copyright © 2020-2023  润新知