扩展中国剩余定理

对于每两个式子(我们考虑将其合并):

{ x ≡ a 1 ( % m 1 ) x ≡ a 2 ( % m 2 ) \left\{ \begin{array}{c} x≡a_1(\% m_1)\\ x≡a_2(\% m_2) \end{array} \right. {xa1(%m1)xa2(%m2)

则有:

{ x = a 1 + k 1 ∗ m 1 x = a 2 + k 2 ∗ m 2 \left\{ \begin{array}{c} x = a_1 + k_1 * m_1\\ x = a_2 + k_2 * m_2 \end{array} \right. {x=a1+k1m1x=a2+k2m2

两式合并:

a 1 + k 1 ∗ m 1 = a 2 + k 2 ∗ m 2 a_1 + k_1 * m_1 = a_2 + k_2 * m_2 a1+k1m1=a2+k2m2

移项得: k 1 ∗ m 1 + ( − k 2 ) ∗ m 2 = a 2 − a 1 k_1 * m_1 + (-k_2) * m_2 = a_2 - a_1 k1m1+(k2)m2=a2a1 (由扩展欧几里得算法解得 k 1 ′ k_1^′ k1 k 2 ′ k_2^′ k2

k 1 k_1 k1的通解为: k 1 = k 1 ′ + k ∗ m 2 g c d ( m 1 , m 2 ) k_1 = k_1^′ + k * \frac{m_2}{gcd(m_1 , m_2)} k1=k1+kgcd(m1,m2)m2

k 1 k_1 k1的通解的求法:利用二元不定方程组的通解
例:将 − k 2 -k_2 k2 看成 k 2 k_2 k2 m 1 , m 2 m_1,m_2 m1,m2 的最大公倍数用 d d d 表示。

k 1 ∗ m 1 + k 2 ∗ m 2 = a 2 − a 1 k_1 * m_1 + k_2 * m_2 = a_2 - a_1 k1m1+k2m2=a2a1
k 1 ′ ∗ m 1 + k 2 ′ ∗ m 2 = a 2 − a 1 k_1^′ * m_1 + k_2^′ * m_2 = a_2 - a_1 k1m1+k2m2=a2a1
两式相减
( k 1 − k 1 ′ ) ∗ m 1 = ( k 2 − k 2 ′ ) ∗ m 2 (k_1 - k_1^′ ) * m_1 = (k_2 - k_2^′ ) * m_2 (k1k1)m1=(k2k2)m2
两边同时约掉最大公倍数 d d d 为:(目的使 m 1 , m 2 m_1,m_2 m1,m2 互质)
不约掉时:设 k = k 1 − k 1 ′ , d = 2 k = k_1 - k_1^′ ,d = 2 k=k1k1d=2 相当与给 k k k 2 2 2 此时 ( k ∗ 2 ) (k*2) (k2) 只能取偶数,不为全部解。

( k 1 − k 1 ′ ) ∗ m 1 d = ( k 2 − k 2 ′ ) ∗ m 2 d (k_1 - k_1^′ ) * \frac{m_1}{d} = (k_2 - k_2^′ ) * \frac{m_2}{d} (k1k1)dm1=(k2k2)dm2

解得:
k 1 = k 1 ′ + k ∗ m 2 d k_1 = k_1^′ + k * \frac{m_2}{d} k1=k1+kdm2
k 2 = k 2 ′ + k ∗ m 1 d k_2 = k_2^′ + k * \frac{m_1}{d} k2=k2+kdm1

k 1 k_1 k1 带入 x = a 1 + k 1 ∗ m 1 x = a_1 + k_1 * m_1 x=a1+k1m1 中,即为 x x x 的通解 x = ( k 1 ′ ∗ m + a 1 ) + k ∗ m 1 m 2 g c d ( m 1 , m 2 ) x = (k_1^′ * m + a_ 1)+ k * \frac{m_1m_2}{gcd(m_1 , m_2)} x=(k1m+a1)+kgcd(m1,m2)m1m2


typedef long long ll;

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


int main()
{
	int n; cin >> n;
	ll a1, m1; cin >> m1 >> a1;
	bool flag = true;
	for (int i = 0; i < n - 1; i++)
	{
		ll a2, m2; cin >> m2 >> a2;
		ll k1, k2; 
		ll d = exgcd(m1, m2, k1, k2);
		if ((a2 - a1) % d) // 判断是否有解
		{
			flag = false;
			break;
		}
		k1 *= (a2 - a1) / d; 
		ll t = m2 / d;
		k1 = (k1 % t + t) % t; //k1 = k1 + k * t 均为k1的解,取最小的一个
		a1 = k1 * m1 + a1;
		m1 = m1 / d * m2;
	}
	if (flag) cout << (a1 % m1 + m1) % m1 << endl;
	else puts("-1");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值