【学习】Exgcd

我们丧心病狂的教练,给我们的本期作业,竟然是

数论

这对于一个数学很渣的小蒟蒻来说,太难了啊

所以开始努力学习数论....的gcd

写这篇blog的原因——洛谷P1082

0X00 需要知道的知识

0X01 定义

gcd:若自然数d同时是自然数a和b的约数,则称d是a和b的公约数。在所有a和b的公约数中最大的一个,称为a和b的最大公约数,计为gcd(a,b)

0X02 定理

证明见lyd《算法竞赛进阶指南》0x32 最大公约数

0X03 九章算术·更相减损术

0X04 欧几里得算法

这个很有用,敲黑板划重点!!

0X10 题解

 0X11 题目

题目描述

求关于xx的同余方程 ax1(mod b) 的最小正整数解。

输入输出格式

输入格式:

一行,包含两个正整数 a,ba,b,用一个空格隔开

输出格式: 

一个正整数 x,即最小正整数解。输入数据保证一定有解。 

输入输出样例

输入样例#1:
3 10
输出样例#1:
 7

0X12 重要的转化

仔细的观察一下这个方程

ax1(mod b)

再看看这个东西

ax+by=1(y为负整数)

哇塞他们是等价的哎

也就是说我们只需要求出一组解使等式成立就行了。且慢,再看一眼题,要求是最小的正整数解,那么只要求出最小的正整数x就完成了

怎么求呢

0X13  EXGCD

扩欧算法出现了!

void exgcd(long long a, long long b)
{
    //当前目的:求解 ax + by = gcd(a, b) 这么一个方程

    if(b == 0) //a, b不断改变的过程中,b最终必然会成为0
    {
        //在 b = 0 时等式还要成立? 使 x = 1, y = 0 ,必然成立 
        x = 1;
        y = 0; 
        return;
    } 

    exgcd(b, a % b);//把下一层系数传进去(先求下一个方程的解 )

    //现在我们已经拿到了下一个方程的解x, y
    long long tx = x;//暂时存一下x,别丢了
    x = y;
    y = tx - a / b * y; 
}

 这就搞定了

//
//  main.cpp
//  Luogu
//
//  Created by gengyf on 2019/5/7.
//  Copyright © 2019 yifan Geng. All rights reserved.
//

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
//#include<bits/stdc++.h>
using namespace std;
long long a,b,x,y;
void exgcd(long xx,long yy){
    if(yy==0){
        x=1;y=0;return ;
    }
    exgcd(yy,xx%yy);
    long long tx=x;
    x=y;
    y=tx-xx/yy*y;
}
int main(){
    scanf("%lld%lld",&a,&b);
    exgcd(a,b);
    while(x<0){
        x+=b;
        x%=b;
    }
    printf("%lld\n",x);
}

  

 

 

 

posted @ 2019-05-15 23:22  喵の耳  阅读(339)  评论(0编辑  收藏  举报