解一元线性同余方程组

定义

a, b是整数,m是正整数,形如ax≡ b(mod m),且x是未知整数的同余式称为一元线性同余方程。

对于ax ≡ b (mod m),可以变形为 ax = b + my,在变形一下就是ax+my = b。这样就把一个一元线性同余方程给转换为可以使用拓展欧几里德求解的形式了。(什么,你和我说你拓展欧几里德都不知道?衰仔,点这里

深入

那今天的重点来了,什么是一元线性同余方程组呢?
就是如下这样的一堆一元线性同余方程放在一起让你求x。
X ≡ r1 (mod a1)
X ≡ r2 (mod a2)
X ≡ r3 (mod a3)
.
.
.
X ≡ rn (mod an)

那对于这样一个方程组,首先我们先对先两个式子进行变换得到
X = r1 + a1y1
X = r2 + a2y2
两个式子相减后得到 r1 + a1y1 = r2 + a2y2
变换一下得到,a1y1 - a2y2 = r2 - r1
设a = a1
b = a2
c = r2 - r1
x = y1
y = y2
方程变换成了ax + by = c
然后通过拓展欧几里德进行求能够求出来x,将x也就是y1回带回去得到一个特解X值(X = r1 + a1 y1)。易得通解X’ = X + k*lcm(a, b),上面式子通过变换能写为 X’ mod lcm(a, b) = X 同余式子就是X’ = X (mod lcm(a, b)) 这样就把前两个式子联立起来了,然后再继续向下进行下去,直到最后化成一个式子就剩下X’ = X (mod lcm(a1, a2…an))。X即为最小的正整数解。

例题

poj3891

模板题没啥说的

#include <iostream>

using namespace std;
typedef long long ll;

void exgcd(ll a, ll b, ll &gcd, ll &x, ll &y)
{
	if (!b)
	{
		gcd = a;
		x = 1;
		y = 0;
	}
	else
	{
		exgcd(b, a%b, gcd, y, x);
		y-=(a/b)*x;
	}
}

int main()
{
	ll n;
	
	while (scanf("%lld", &n) != EOF)
	{
		ll a1, r1, a2, r2, a, b, c, d, x0, y0;
		bool flag = true;
		
		scanf("%lld %lld", &a1, &r1);
	
		for (int i=0; i<n-1; i++)
		{
			scanf("%lld %lld", &a2, &r2);
			
			a = a1, b = a2, c = r2-r1;
			exgcd(a, b, d, x0, y0);
			
			if (c%d != 0)
			{
				flag = false;
			}
			
			int t = b/d;
			x0 = (x0*(c/d)%t+t) % t;
			r1 = a1*x0+r1;
			a1 = a1*(a2/d);
		}
		
		if (flag)
		{
			printf("%lld\n", r1);
		}
		else
		{
			printf("-1\n");
		}
	}
	
	return 0;
} 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值