同余与二元一次方程求解(上)

同余方程

同余:

设m是正整数,若 a a a b b b是整数,且 m ∣ ( a − b ) m|(a-b) m(ab)(意思是 a − b a-b ab能被 m m m整除),则 a a a b b b m m m同余 , a ≡ b ( m o d m ) ,a \equiv b \pmod {m} ab(modm) ,也就是说 a a a除以 m m m的余数等于 b b b除以 m m m的余数

现在我们考虑一元线性同余方程 a x ≡ b ( m o d m ) a x \equiv b \pmod {m} axb(modm) , a > 0 , n > 0 ,a>0,n>0 ,a>0,n>0
它表示 a x − b ax-b axb m m m的倍数,设为 − y -y y倍,则有二元线性丢番图方程 a x + m y = b ax+my=b ax+my=b,即求解一元线性同余方程等价于求解二元线性丢番图方程

如何求二元线性丢番图方程呢?

先给出一个推论:当且仅当 g c d ( a , m ) ∣ b gcd(a,m)|b gcd(a,m)b的时候,方程对于未知量 x x x g c d ( a , m ) gcd(a,m) gcd(a,m)个模 m m m不同余的解,另外,如果 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)是方程的一个特解,那么所有的通解可以表示为 x = x 0 + n ( b / g c d ( a , m ) ) , y = y 0 − n ( a / g c d ( a , m ) ) x=x_0+n(b/gcd(a,m)),y=y_0-n(a/gcd(a,m)) x=x0+n(b/gcd(a,m)),y=y0n(a/gcd(a,m)),其中 n n n为任意正整数

证明:
a = g c d ( a , m ) a ′ , m = g c d ( a , m ) m ′ a=gcd(a,m)a',m=gcd(a,m)m' a=gcd(a,m)a,m=gcd(a,m)m,有 a x + m y = g c d ( a , m ) ( a ′ x + m ′ y ) = b ax+my=gcd(a,m)(a'x+m'y)=b ax+my=gcd(a,m)(ax+my)=b,所以如果 a a a m m m都是整数,那 b b b也必须是 g c d ( a , m ) gcd(a,m) gcd(a,m)的整数倍才有整数解

所以问题转化为怎么求出这个二元方程 a x + m y = b ax+my=b ax+my=b的一个特解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),既然 g c d ( a , m ) ∣ b gcd(a,m)|b gcd(a,m)b,不如先求出 a x ′ + m y ′ = g c d ( a , m ) ax'+my'=gcd(a,m) ax+my=gcd(a,m),最后左右两边都乘以 b / g c d ( a , m ) b/gcd(a,m) b/gcd(a,m),

a x + m y = g c d ( a , m ) ax+my=gcd(a,m) ax+my=gcd(a,m) 扩展欧几里得算法

  • m = 0 m=0 m=0时, x = 1 , y = 0 x=1,y=0 x=1,y=0时等式成立
  • m > 0 m>0 m>0时,已知: g c d ( a , m ) = g c d ( m , a − m ) = g c d ( m , a gcd(a,m)=gcd(m,a-m)=gcd(m,a gcd(a,m)=gcd(m,am)=gcd(m,a% m ) , a m),a m),a% m = a − m ∗ a / m m=a-m*a/m m=ama/m
    则有 m x + ( a mx+(a mx+(a% m ) y = g c d ( m , a m)y=gcd(m,a m)y=gcd(m,a% m ) = g c d ( a , m ) m)=gcd(a,m) m)=gcd(a,m)
    m x + ( a − m ∗ a / m ) y = g c d ( m , a mx+(a-m*a/m)y=gcd(m,a mx+(ama/m)y=gcd(m,a% m ) = g c d ( a , m ) m)=gcd(a,m) m)=gcd(a,m)
    a y + m x − ( a / m ) ∗ m y = g c d ( a , m ) ay+mx-(a/m)*my=gcd(a,m) ay+mx(a/m)my=gcd(a,m)
    a y + m ( x − a / m ∗ y ) = g c d ( a , m ) ay+m(x-a/m*y)=gcd(a,m) ay+m(xa/my)=gcd(a,m)

对比 m x + a mx+a mx+a% m ∗ y = g c d ( a , m ) m*y=gcd(a,m) my=gcd(a,m)
所以 x = y , x=y, x=y, y = ( x − a / m ∗ y ) , y=(x-a/m*y), y=(xa/my), a = m , a=m, a=m, m = a m=a m=a% m m m

typedef long long ll;
ll extend_gcd(ll a,ll m,ll &x,ll &y){//返回特解x0,y0
	if(m==0){
		x=1;y=0;
		return a;
	}else{
		ll d=extend_gcd(m,a%m,y,x);//swap(x,y)
		y-=(a/m)*x;//x,y交换了,这句容易出错
		return d;//返回gcd(a,m)
	}
}

得到了 a x ′ + m y ′ = g c d ( a , m ) ax'+my'=gcd(a,m) ax+my=gcd(a,m)的特解 ( x 0 ′ , y 0 ′ ) (x_0',y_0') (x0,y0)
a x + m y = b ax+my=b ax+my=b的特解为 x 0 = x 0 ′ ∗ b / g c d ( a , m ) , y 0 = y 0 ′ ∗ b / g c d ( a , m ) x_0=x_0'*b/gcd(a,m),y_0=y_0'*b/gcd(a,m) x0=x0b/gcd(a,m),y0=y0b/gcd(a,m)
通解为 x = x 0 + n ∗ ( b / g c d ( a , m ) ) , y = y 0 − n ∗ ( a / g c d ( a , m ) ) x=x_0+n*(b/gcd(a,m)),y=y_0-n*(a/gcd(a,m)) x=x0+n(b/gcd(a,m)),y=y0n(a/gcd(a,m))

x=x0 + n*(b/__gcd(a,m));
y=y0 - n*(b/__gcd(a,m));

对于同余方程 a x ≡ b ( m o d m ) a x \equiv b \pmod {m} axb(modm) , a > 0 , n > 0 ,a>0,n>0 ,a>0,n>0
调用 e x t e n d extend extend_ g c d ( a , m , x , y ) gcd(a,m,x,y) gcd(a,m,x,y),得出的 x 0 x_0 x0就是一个解,通解 x = x 0 + ( m / g c d ( a , m ) ) ∗ n x=x_0+(m/gcd(a,m))*n x=x0+(m/gcd(a,m))n 0 ≤ n ≤ d − 1 0\le n\le d-1 0nd1.,当 n 从 0 到 d − 1 n从0到d-1 n0d1,就取遍了模d的完全剩余系

x=x0+(m/__gcd(a,m))*n;

P1082

题目描述

求关于 x x x 的同余方程 a x ≡ 1 ( m o d b ) a x \equiv 1 \pmod {b} ax1(modb) 的最小正整数解。

输入格式

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

输出格式

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

样例 #1

样例输入 #1

3 10

样例输出 #1

7

数据规模与约定

  • 对于 100 % 100\% 100% 的数据, 2 ≤ a , b ≤ 2 , 000 , 000 , 000 2 ≤a, b≤ 2,000,000,000 2a,b2,000,000,000

a x ≡ 1 ( m o d b ) a x \equiv 1 \pmod {b} ax1(modb)即方程 a x + m y = 1 ax+my=1 ax+my=1,先用 e x t e n d extend extend_ g c d ( ) gcd() gcd()求出一个特解,然后用取模运算来得出最小正整数解

x=(x%m+m)%m;//保证返回正整数解

补充

a x ≡ 1 ( m o d b ) a x \equiv 1 \pmod {b} ax1(modb)的解,为 a a a m m m的逆,记为 a − 1 a^{-1} a1,所以扩展欧几里得算法就可以用来求逆,下面再介绍一种求逆的方法
费马小定理:设n是素数,a是正整数且与n互素,有 a n − 1 ≡ 1 ( m o d n ) a^{n-1}\equiv 1 \pmod {n} an11(modn)

a ∗ a n − 2 ≡ 1 ( m o d n ) a*a^{n-2}\equiv1\pmod {n} aan21(modn),那按照 a n − 2 ( m o d n ) a^{n-2}\pmod {n} an2(modn)就是 a a a n n n的逆!!!这个部分计算用快速幂取模来操作
但是!!!仅用费马小定理来测试素数是很危险的,原因是存在少量的伪素数也满足费马小定理,被称为Carmichael数,一亿个数里面大约有200多个,
欧几里得算法(辗转相除法)

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

Thanks♪(・ω・)ノ

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值