【洛谷P1082】同余方程【扩欧】

本文探讨了如何求解形如ax≡1(modb)的同余方程,通过将其转化为线性不定方程,利用扩展欧几里得算法求解一组特解,进而找出最小正整数解的方法。

题目大意:

题目链接:https://www.luogu.org/problem/P1082
求关于 x x x的同余方程 a x ≡ 1 ( m o d b ) ax \equiv 1 \pmod {b} ax1(modb)的最小正整数解。


思路:

数论是真的差,现在才来补 q w q qwq qwq
我先把原式改写为等式的形式。
a x ≡ 1 ( m o d b ) ax \equiv 1 \pmod {b} ax1(modb)
a x − b y = 1 ax-by=1 axby=1
然后设 x ′ y ′ x'y' xy为方程 b x ′ − ( a m o d    b ) y ′ = 1 bx'-(a\mod b)y'=1 bx(amodb)y=1的一组解。
即为 b x ′ − y ′ ( a − ⌊ a b ⌋ ) bx'-y'(a-\lfloor\frac{a}{b}\rfloor) bxy(aba)的一组解。
统一格式为
a y ′ − b ( x ′ − y ′ a b ) ay'-b(x'-\frac{y'a}{b}) ayb(xbya)
那么代入 x = y , y = x ′ − y ′ a b x=y,y=x'-\frac{y'a}{b} x=y,y=xbya即可。
因为 g c d ( x , 0 ) = x gcd(x,0)=x gcd(x,0)=x,当 b = 0 b=0 b=0时,必然有 a = 1 a=1 a=1。此时该方程的解为 x = 1 , y = 0 x=1,y=0 x=1,y=0
然后往上回溯求解即可。
最终我们可以得到该方程的一组解 ( x , y ) (x,y) (x,y),由于要求 x x x尽量小且大于0,我们发现为了满足 a x + b y = 1 ax+by=1 ax+by=1 Δ a x \Delta ax Δax必然等于 Δ b y \Delta by Δby,那么同时要满足 x , y x,y x,y均为整数,所以需要找到一组合法的 ( x ′ , y ′ ) (x',y') (x,y)使得 a ( x ± x ′ ) = b ( y ± y ′ ) a(x±x')=b(y±y') a(x±x)=b(y±y)
所以 Δ a x \Delta ax Δax Δ b y \Delta by Δby最小等于 l c m ( a , b ) lcm(a,b) lcm(a,b)。所以 Δ x \Delta x Δx每次最小为 b l c m ( a , b ) \frac{b}{lcm(a,b)} lcm(a,b)b
那么就让 x x x不停加减 b l c m ( a , b ) \frac{b}{lcm(a,b)} lcm(a,b)b,知道 x x x为最小的正整数解为止。其实不断加减就是进行一次取模运算即可。


代码:

#include <cstdio>
#include <algorithm>
#define mp make_pair
#define st first
#define nd second
using namespace std;

int a,b;

pair<int,int> exgcd(int a,int b)
{
	if (b)
	{
		pair<int,int> x=exgcd(b,a%b);
		return mp(x.nd,x.st-x.nd*(a/b));
	}
	return mp(1,0);
}

int main()
{
	scanf("%d%d",&a,&b);
	int x=exgcd(a,b).first,y=b/__gcd(a,b);
	printf("%d",(x%y+y)%y);
	return 0;
} 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值