同余方程 + 乘法逆元

同余方程  分析:为了介绍扩展欧几里得,先介绍一下贝祖定理:即如果a、b是整数,那么一定存在整数x、y使得ax + by = gcd(a, b)。  即如果ax + by = m有解,那么m一定是gcd(a, b)的若干倍。(可以来判断一个这样的式子有没有解)  有一个直接的推论:如果ax + by = 1有解,那么gcd(a, b) = 1,也就是说a和b互质。  如果我们想要求出a和b的最大公因数gcd(a, b),最容易想到的就是古老悠久而又相当强大的辗转相除法:int gcd(int a,
摘要由CSDN通过智能技术生成

同余方程

题目描述

  求关于x的同余方程 ax ≡ 1 ( mod b ) 的最小正整数解。

输入格式

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

输出格式

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

输入输出样例
输入

3 10

输出

7

洛谷p1082

分析:

  为了介绍扩展欧几里得,先介绍一下贝祖定理:即如果a、b是整数,那么一定存在整数x、y使得ax + by = gcd(a, b)。
  即如果ax + by = m有解,那么m一定是gcd(a, b)的若干倍。(可以来判断一个这样的式子有没有解)
  有一个直接的推论:如果ax + by = 1有解,那么gcd(a, b) = 1,也就是说a和b互质。
  如果我们想要求出a和b的最大公因数gcd(a, b),最容易想到的就是古老悠久而又相当强大的辗转相除法:

int gcd(int a, int b){
   
	return b == 0 ? a : gcd(b, a % b);
}

  但是,对于上面的式子ax + by = m来说,我们并不仅仅想要知道有没有解,而是想要知道在有解的情况下这个解到底是多少。所以,这里要运用扩展欧几里得解决此问题。
  我们对前面求两数的最大公因数的代码进行分析:当到达递归边界的时候,b == 0,a = gcd(a, b) 这时可以观察出来这个式子的一个解:a * 1 + b * 0 = gcd(a, b),x = 1, y = 0,注意这时的a和b已经不是最开始的那个a和b了,所以我们如果想要求出解x和y,就要回到最开始的模样。
  初步想法:由于是递归的算法,如果我们知道了这一层和上一层的关系,一层一层推下去,就可以推到最开始的。类似数学上的数学归纳法。假设当前我们在求的时a和b的最大公约数,而我们已经求出了下一个状态:b 和 a % b的最大公因数,并且求出了一组 x1和y1使得b * x1 + (a % b) * y1 = gcd(注意:在递归算法中,永远都是先得到下面一个状态的值)。
  这时我们可以试着去寻找这两个相邻状态的关系:首先我们知道:a % b = a - (a / b) * b;
代入: b * x1 + (a - (a / b) * b) * y1
  = b * x1 + a * y1 – (a / b) * b * y1
  = a * y1 + b * (x1 – a / b * y1) = gcd
可以发现 :x = y1 , y = x1 – a / b * y1
  这样我们就得到了每两个相邻状态的x和y的转化,就可以在求gcd的同时对x和y进行求值了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
int read(){
   
	int x, f = 1;
	char ch;
	while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
	x = ch - '0';
	while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
	return x * f;
}
int exgcd(int a,int b,int &x,int &y){
   //扩展欧几里得算法
    if(b == 0){
   
        x = 1; y = 0;
        return a;  	//到达递归边界开始向上一层返回
    }
    int r = exgcd(b, a % b, x, y);
    int temp = y;    	//把x y变成上一层的
    y = x - (a / b) * y;
    x = temp;
    return r
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值