辗转相除的层数—变量出了问题

思路:

  a+b尽量小 ,极限情况就是b=a+x.

  同理 a=x+z.

  于是z+x=a, x+a=b,..a+b=c,b+c=d.......像是一个广义斐波那契数列。

  F(a,b)=1,中 a+b最小的 是(1,1)。

  所以,是个标准的斐波那契数列。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MOD 1000000007
using namespace std;
struct node{
    int  v[2][2]; //注意最好开 long log
}ans,f,ans1;
long long k;
node ch(node a,node b)
{

    for(int i=0;i<=1;i++)
    for(int j=0;j<=1;j++)
    {
        ans1.v[i][j]=0;
        for(int kk=0;kk<=1;kk++)
            ans1.v[i][j] = ( 1LL*ans1.v[i][j]+(1LL*a.v[i][kk]*b.v[kk][j])%MOD +MOD)%MOD;    //   没提前转化成(long long )再 取模,溢出后再取模就错了
    }
    return ans1;
}
void fastlow()
{
    while(k)
    {
        if(k%2)    ans=ch(ans,f);
        k/=2; f=ch(f,f);
    }
}
int main()
{
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    cin>>k;
    if(k==1)
    {
        printf("1 1");
        return 0;
    }
    ans.v[0][0]=1;ans.v[0][1]=1;ans.v[1][0]=ans.v[1][1]=0;
    f.v[0][0]=1,f.v[0][1]=1,f.v[1][0]=1;f.v[1][1]=0;
    fastlow();
    printf("%d %d\n",(ans.v[0][1]+MOD)%MOD,(ans.v[0][0]+MOD)%MOD);
    return 0;
}
时间: 2024-10-08 08:16:02

辗转相除的层数—变量出了问题的相关文章

辗转相除的层数

#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<cmath> #define MOD 1000000007 using namespace std; struct node{ int v[2][2]; //注意最好开 long log }ans,f,ans1; long long k;

欧几里德(辗转相除发)算法

辗转相除,又名欧几里德算法(Euclidean algorithm)乃求两个正整数之最大公约数的算法. 此处用函数的递归调用编写了一个小程序: int gcd(int a,int b){ if(a%b==0) return b; else return gcd(b,a%b);} 非递归调用则: int gcd(int a,int b){ int temp; while(a%b!=0) { temp=b; b=a%b; a=temp; } return b;} 通常情况下在gcd(a,b)=1的情

codeforces 267A A. Subtractions(辗转相除)

题目链接: codeforces 267A 题目大意: 给出一个数对,(a,b)每次用较大的减较小的,直到出现0为止,问要进行多少次操作. 题目分析: 大的减小的操作,可以利用取模优化过程,也就是辗转相除,商是操作次数,余数是下一段与之前较小的数继续进行操作的数,水题不做赘述. AC代码: #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using n

bzoj 2852: 强大的区间 辗转相除

2852: 强大的区间 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 45  Solved: 12[Submit][Status][Discuss] Description curimit很喜欢区间,最近发现了一种很强大的区间. curimit发现有的区间虽小,比如 (1.99998, 2.000001),但是其中却包含了一个整数2. 但是有的区间较大,比如(1.0001, 1.99998),但是其中却一个整数都没有. 他觉得包含整数的区间很强大,

【c语言】关于临时变量出其作用域就释放的例子

// 关于临时变量出其作用域就释放的例子 #include <stdio.h> // 临时变量s出函数作用域就销毁了,该空间里就是随机值 unsigned short *sum(unsigned char a, unsigned char b) { unsigned short s = 0; s = a + b; return &s; } int main() { unsigned short *p = NULL; unsigned char a = 1, b = 2; p = sum

POJ 2348 Euclid&#39;s Game(辗转相除博弈+自由度分析)

题目链接:http://poj.org/problem?id=2348 题目大意:给你两个数a,b,Stan和Ollie轮流操作,每次可以将较大的数减去较小的数的整数倍,相减后结果不能小于0,谁先将其中一个数字变成0谁就获胜. 解题思路:看了挑战程序设计上的,这里我们先假设a<b,当b是a的整数倍是必胜态.我们讨论以下b不是a的整数倍,此时a,b的关系按照自由度的观点(第一次听说),可以分为以下两种情况: ①b-a<a ②b-a>a 那么对于①,玩家只有从b中减去a这一个选择.如果b-a

欧几里德算法(辗转相除)证明

过了这么久,终于知道了辗转相处的证明了,以前只是记住了,但不是真的很理解,现在写一下它的证明,以便下次忘了的时候看一下.辗转相除是求两个数的最大公约数的. 要证这个定理成立,只需要证明 gcd(a, b) = gcd(b, a % b) 就行了 证明:令a % b = r, 所以a = k * b + r, 所以r = a - k * b,假设d为a,b的一个公约数,那么 d|a,  d|b,(d|a的意思就是d整除a,也就是a能被d整除),所以a - k * b 也一定能被d整除,即 d|r,

求两个正整数的最大公约数——辗转相减法

问题:求解两个正整数的最大公约数 今天第一节形式化方法课,举了一个简单的例子——辗转相减法求解两个正整数的最大公约数,来讲解形式化方法的基本内容,让我们有感性的认识.其基本思路如下: 1.任意给定两个正整数a和b: 2.若a和b不相等,则执行第3步: 3.选择a.b中较大者,将较大者与较小者的差赋值给较大者: 4.判断重新赋值后的a和b是否相等,若不相等则继续执行第3步,否则执行第5步: 5.返回a或b. 程序如下(Java编写). 程序中前断言和后断言是形式化方法中的内容,前断言判断用于计算的

[SDOI2009]SuperGCD 【压位高精度+辗转相减】

题目链接: https://www.luogu.org/problemnew/show/P2152 题目概述:  计算两个大整数(A,B)的最大公因数 数据范围 0 < A , B ≤ 10 ^ 其一在于辗转相减法--辗转相除法的优化(针对大数,避免了大数的模运算带来的多方面的复杂度) 思想就是 以数次 A-B  代替 A%B (这二者是等价的) 辗转相减法: 1 /* 2 Write(X) 输出X 3 Down(X) X除以2 4 Up(X) X乘以2 5 */ 6 void Solve(){