中国剩余定理学习 && 拓展中国剩余定理

中国剩余定理学习 && 拓展中国剩余定理

中国剩余定理:

仅供自己复习时查看一下大佬笔记,详细学习过程在大佬的博客

学习连接:https://www.cnblogs.com/MashiroSky/p/5918158.html

拓展中国剩余定理:

中国剩余定理在求解同余方程组的时候,要求模数之间是互质的,那么假如模数没有说明一定是互质的,这时就要用到了我们的拓展中国剩余定理( e x c r t excrt excrt),拓展中国剩余定理其实和中国剩余定理联系不大,我觉得是因为它是用 e x g c d exgcd exgcd退出,并且与其联系紧密所以叫这个名字。
同余方程组:
{ x ≡ r 1   ( m o d   m 1 ) x ≡ r 2   ( m o d   m 2 ) . . x ≡ r n   ( m o d   m n ) \begin{cases}x \equiv r_1\ (mod\ m_1) \\x \equiv r_2\ (mod\ m_2) \\..\\x \equiv r_n\ (mod\ m_n) \\ \end{cases} xr1 (mod m1)xr2 (mod m2)..xrn (mod mn)
考虑最开始的两个式子 { x ≡ r 1   ( m o d   m 1 ) x ≡ r 2   ( m o d   m 2 ) \begin{cases}x \equiv r_1\ (mod\ m_1) \\x \equiv r_2\ (mod\ m_2) \end{cases} {xr1 (mod m1)xr2 (mod m2)
x = r 1 + k 1 ∗ m 1 x = r_1 +k_1 * m_1 x=r1+k1m1 x = r 2 + k 2 ∗ m 2 x = r_2 + k_2 * m_2 x=r2+k2m2,得 r 1 + k 1 ∗ m 1 = r 2 + k 2 ∗ m 2 r_1 + k_1*m_1 = r_2 + k_2*m_2 r1+k1m1=r2+k2m2,移项的, r 2 − r 1 = k 1 ∗ m 1 + ( − k 2 ) ∗ m 2 = k 1 ∗ m 1 + k 2 ∗ m 2 r_2 - r_1 = k_1*m_1 + (-k_2)*m_2 = k_1 * m_1 + k_2 * m_2 r2r1=k1m1+(k2)m2=k1m1+k2m2,这样这个式子就变成类似 a x + b y = c ax + by = c ax+by=c的形式了,于是我们求
K 1 ∗ m 1 + K 2 ∗ m 2 = g c d ( m 1 , m 2 ) K_1*m_1+K_2 * m_2 = gcd(m1,m2) K1m1+K2m2=gcd(m1,m2),得到 K 1 K_1 K1后两边同时乘上 ( r 2 − r 1 ) g c d ( m 1 , m 2 ) \frac {(r2 - r1)}{gcd(m_1,m_2)} gcd(m1,m2)(r2r1),可得 k 1 = K 1 ∗ ( r 2 − r 1 ) g c d ( m 1 , m 2 ) k_1 = K_1 * \frac {(r2 - r1)}{gcd(m_1,m_2)} k1=K1gcd(m1,m2)(r2r1),这样把 k 1 k_1 k1在转化为最小的正数解之后,就可以用得到一个特解
x ∗ = k 1 ∗ m 1 + r 1 x^* = k_1 * m_1 + r_1 x=k1m1+r1,怎么通过这个特解去获得一个同余方程呢,观察前面的式子
{ x = r 1 + K 1 ∗ ( r 2 − r 1 ) g c d ( m 1 , m 2 ) ∗ m 1 x = r 2 + K 2 ∗ ( r 2 − r 1 ) g c d ( m 1 , m 2 ) ∗ m 2 \begin{cases}x = r_1 + K_1 * \frac {(r2 - r1)}{gcd(m_1,m_2)} * m_1\\ x = r_2 + K_2 * \frac {(r2 - r1)}{gcd(m_1,m_2)} * m_2 \end{cases} {x=r1+K1gcd(m1,m2)(r2r1)m1x=r2+K2gcd(m1,m2)(r2r1)m2
可以看到任意两个解之间的差值一定是 m 1 ∗ m 2 g c d ( m 1 , m 2 ) \frac {m_1 * m_2}{gcd(m1,m2)} gcd(m1,m2)m1m2的倍数,也就是我们的特解 x ∗ + t ∗ l c m ( m 1 , m 2 ) = x ( 通 解 ) x^* + t * lcm(m1,m2) = x(通解) x+tlcm(m1,m2)=x(),到此也就能看出新的同余方程就是 x ≡ x ∗   ( m o d   l c m ( m 1 , m 2 ) ) x \equiv x^*\ (mod\ lcm(m1,m2)) xx (mod lcm(m1,m2))
所以对于n组方程我们只需要不断两两进行合并,更新合并出的方程组的对应的值,合并n-1次就可以得到一个最终的同余方程,最后的答案即为我们求得。

一些具体实现细节,需要结合代码加深理解。

例题:POJ2891 模板题

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>

using namespace std;
#define int long long
#define pb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int MAXN = 1e5 + 7;
int n;
int mod[MAXN],r[MAXN];//分别代表模数数组 和 余数数组
int exgcd(int a,int b,int &x,int &y) {
	if(b == 0) {
		x = 1; y = 0;
		return a;
	}
	else {
		int res = exgcd(b,a%b,x,y);
		ll t = x;
		x = y;
		y = t - a / b * y;
		return res;
	}
}
int excrt() {//就是一个不断合并并且更新新的参数的过程
	int MOD = mod[1],R = r[1],x,y;
	for(int i = 2;i <= n;i ++) {
		int g = exgcd(MOD,mod[i],x,y);
		if((r[i] - R) % g != 0) return -1;//同余方程组无解
		x = x * (r[i] - R) / g;
		x = (x % (mod[i] / g) + (mod[i] / g)) % (mod[i] / g);//得到最小的解
		R = x * MOD + R;
		MOD = MOD / g * mod[i];//合并之后的模数 应该是lcm
		R = R % MOD;//重新取一遍得到合并后的新的同余方程
	}
	return (R % MOD + MOD) % MOD;
}

signed main() {
	while(~scanf("%lld",&n)) {
		for(int i = 1;i <= n;i ++) {
			scanf("%lld%lld",&mod[i],&r[i]);
		}
		int ans = excrt();
		printf("%lld\n",ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值