扩展欧几里得算法、不定方程、同余方程、乘法逆元求解

不定方程理论

设 k ≥ 2,c, a1 ,..., ak是整数且 a1 ,..., ak都不等于零,以及 x1 ,..., xk是整数变数,则方程

   a1x1+...+akxk=c           (1)

称为 k 元一次不定方程 a1 ,..., ak称为它的系数

求解方法理论

:不定方程有解的充分必要条件是它的系数的最大公约数(a1, ... ,ak)|c。并且,不定方程(1)有解时,它的解和不定方程

a1gx1+ ... +akgxk=cg      (2)

的解相同,这里 g=(a1, ... ,ak)

必要性显然。下面来证充分性,若 g | c,设 c=gc1,又g = (a1, ... ,ak) 必然可以表示为a1, ... ,ak的所有整系数线性组合中最小的正整数,则必有整数 y1,0, ... ,yk,0,使得

  a1y1,0+ ... +akyk,0=g      (3)

因此x1=c1y1,0, ... ,xk=ckyk,0 即为 (1) 的一组解,这就证明了充分性。由于 (1) 有解时必有 g | c,而此时不定方程 (1) 和 (2) 是同一个方程,这就证明了后一结论。

:设二元一次不定方程

       a1x1+a2x2=c                 (4)

有解,x1,0, x2,0 是它的一组解,那么它的所有解为

{x1=x1,0+a2(a1,a2)t                                      t=0, ±1 ,±2,...x2=x2,0a1(a1,a2)t

容易直接验证由式 (5) 给出的,对所有整数 t 都满足不等式(4)。反过来,设x1, x2 是 (4) 的一组解,那么我们有

a1x1+a2x2=c=a1x1,0+a2x2,0

进而有

a1(x1x1,0)=a2(x2x2,0)

a1(a1,a2)(x1x1,0)=a2(a1,a2)(x2x2,0)

又因为 (a1(a1,a2)),a2(a1,a2))=1,则由定理知,

扩展欧几里得算法

求 ax + by = gcd(a, b) 的一组整数解

扩展欧几里得算法:

(1)当 b = 0时,ax + by = a,故 x = 1,b = 0

(2)当 b ≠ 0时,由欧几里得算法,gcd(a, b) = gcd(b, a % b)

由裴蜀定理,得

gcd(a,b)=ax+by

       gcd(b,a%b)=bx1+(a%b)y1

                                       =bx1+(aab×b)y1

                                   =ay1+b(x1aby1)

所以 x=y1, y=x1acy1。故可以用递归算法,先求出下一层的x1, y1。再回代到上一层,层层回代,即可求出特解 (x0, y0)

构造通解

{y=x0+bgcd(a,b)t                                      t=0, ±1 ,±2,...x=y0agcd(a,b)t

模板: 时间复杂度 :O(logn)

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

求解不定方程

求 ax + by = c 的一组整数解

求解步骤:

若 gcd(a, b) | c,则有整数解,先用扩欧算法求 ax + by = gcd(a, b) 的解,再乘以 c / gcd(a, b),即得原方程的特解x0,y0

模板:时间复杂度 :O(logn)

int main()
{
int a, b, c;
cin >> a >> b >> c;
int x, y;
int d = exgcd(a, b, x, y);
if(c % d == 0) printf("%d %d\n", c/d * x, c/d * y);
else puts("No solution");
return 0;
}

求解同余方程

给定整数a,b,m,求解同余方程 ax ≡ b (mod m)。

如果 x 存在整数解,则输出任意一个;

如果不存在,则输出 No solution。

例:8x ≡ 4 (mod 6),整数解 x = 2

求解步骤:

  1. 把同余方程转化成不定方程

    由 ax ≡ b (mod m)

    得 ax = m(-y) + b

    即 ax + my = b

    又有裴蜀定理,当 gcd(a, m) | b时有解

  2. 用扩欧算法,求 ax + my = gcd(a, m)的解,然后把 x 乘以 b / gcd(a, m) 即得原方程的特解。

模板:时间复杂度 :O(logn)

int main()
{
int a, b, m;
cin >> a >> b >> m;
int x, y;
int d = exgcd(a, m, x, y);
if(b % d == 0) printf("%d\n", 1ll*x * b / d);
else printf("No solution\n");
return 0;
}

求解乘法逆元

给定整数a,m,且 a 与 m互质时,对于同余方程 ax ≡ 1 (mod m)。求 a 的乘法逆元 x (0 < x < m)

例: 3x ≡ 1 (mod 4),整数解 x = 3

求解步骤:

  1. 乘法逆元转化不定方程,等价变形 ax + my = 1。
  2. 扩欧算法 求 ax + my = gcd(a, m) 的解 x(由于此时 x / gcd(a, m) = x),之后 (x % m + m) % m即为答案。

技巧:“模加模”保证最小正整数

例:x = -7, m = 5,则(-7 % 5 + 5) % 5 = 3

例:x = 7, m = 5,则(7 % 5 + 5) % 5 = 2

模板:时间复杂度 :O(logn)

int main()
{
int a, m;
cin >> a >> m;
int x, y;
int d = exgcd(a, m, x, y);
if(d == 1) printf("%d\n", (x % m + m) % m); // a, m互质才有逆元
return 0;
}
posted @   straySheep  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示