扩展欧几里得算法

扩展欧几里得算法

数学推导

现有一二元一次方程:
a x 1 + b y 1 = m ax_{1}+by_{1}=m ax1+by1=m
a x 2 + b y 2 = g c d ( a , b ) ax_{2}+by_{2}=gcd(a,b) ax2+by2=gcd(a,b)
由数学中的某一定理可知(裴蜀定理,直接用结论),当二元一次方程的结果 m m m是两系数的最大公因数或是最大公因数的倍数,则我们可以得至少有一组整数解可以满足方程。

x 1 % x 2 = = y 1 % y 2 = = 0   , x 1 / x 2 = = y 1 / y 2 x_{1}\% x_{2} == y_{1}\% y_{2} == 0\ , x_{1}/ x_{2} == y_{1}/ y_{2} x1%x2==y1%y2==0 ,x1/x2==y1/y2

现有一算法通过gcd的性质扩展可以求得一组 x 2 , y 2 x_{2} , y_{2} x2,y2

int exgcd(int a ,int b ,int &x , int &y){
    if(!b){
        x = 1 , y = 0 ;
        return a ; 
    }
    else {
        int d = exgcd(b , a%b , y , x) ;
        y = y - (a/b) * x ;
        return d ;
    }
}

同余方程(ACwing878)

原题

题目描述

给定 n 组数据 ai,bi,mi,对于每组数求出一个 x i x_{i} xi,使其满足 a i × x i ≡ b i ( m o d   m i ) a_{i}×x_{i}≡b_{i}(mod\ m_{i}) ai×xibi(mod mi) ,如果无解则输出 impossible

输入格式

第一行包含整数 n n n

接下来 n n n 行,每行包含一组数据 a i , b i , m i a_{i},b_{i},m_{i} ai,bi,mi

输出格式

输出共 n n n 行,每组数据输出一个整数表示一个满足条件的 x i x_{i} xi,如果无解则输出 impossible

每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。

输出答案必须在 int 范围之内。

数据范围

1 ≤ n ≤ 1 0 5 , 1≤n≤10^{5}, 1n105,
1 ≤ a i , b i ≤ 2 × 1 0 9 1≤a_{i},b_{i}≤2×10^{9} 1ai,bi2×109

样例
2
2 3 6
4 3 5
impossible
-3
思路

a i × x i ≡ b i ( m o d   m i ) a_{i}×x_{i}≡b_{i}(mod\ m_{i}) ai×xibi(mod mi)
可以转化为
a i × x i − m i × y i = b i a_{i}×x_{i}-m_{i}\times y_{i} =b_{i} ai×ximi×yi=bi
y i = − y i y_{i} = -y_{i} yi=yi

a i × x i + m i × y i = b i a_{i}×x_{i}+m_{i}\times y_{i} =b_{i} ai×xi+mi×yi=bi
之后便可利用扩展欧几里得解

#include <iostream>
using namespace std ;

typedef long long ll ;

int exgcd(int a , int b , int &x ,int &y){
    if(!b){
        x = 1 ,y = 0 ;
        return a ;
    }
    int d = exgcd(b , a%b , y , x );
    y -= a/b * x ;
    return d ;
}


int main(){
    int n ; 
    cin >> n ;
    while(n -- ){
        int a ,b , m ;
        cin >> a >> b >> m ;
        int x ,y ;
        int d = exgcd(a , m , x , y ) ;
        
        if(b%d) puts("impossible");
        else cout <<  ((ll)x * b / d % m + m) % m << endl ;
        
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值