P4777 【模板】扩展中国剩余定理(EXCRT)

题目描述

给定 n 组非负整数 ai​,bi​ ,求解关于 x 的方程组的最小非负整数解。

x≡b1​ (mod a1​)

x≡b2​ (mod a2​).

x≡bn​ (mod an​)​

输入格式

输入第一行包含整数 n。

接下来 n 行,每行两个非负整数 ai​,bi​。

输出格式

输出一行,为满足条件的最小非负整数 x。

输入输出样例

输入 #1复制

3
11 6
25 9
33 17

输出 #1复制

809

说明/提示

对于 100% 的数据,1≤n≤105,1≤bi​,ai​≤1012,保证所有 ai​ 的最小公倍数不超过 10181018。

请注意程序运行过程中进行乘法运算时结果可能有溢出的风险。

数据保证有解。

解析:

中国剩余定理扩展:

当mi他们两两不互质的时候,x  = a*q1 + r1 , x = b*q1 + r2;

a*q1 + r1 = b* q2 + r2  移项可得 a*q1 + b*q2 =  r2 - r1

由裴蜀定理 :

当 gcd(a,b) | r2 - r1  则有解,否则无解 。

这时我们可以利用扩展的欧拉定理求解 特解 :q1   = p * (r2 - r1) /gcd(a,b)

并对其求通解: P = q1 + b / gcd(a ,b )*K  (K为任意常数)

编程思路:

第一个方程我们只需要记录 其 摩数 和 余项

对后后面的方程进行 合并:extend_gcd(a, b, x, y);

扩张欧几里得代码:

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

求出了 当前合并的 m 和 下个 mi的 最大公倍数和 (ax+by = 1)中x的值 

然后求 通项:x = x*c /d; 因为x 可以扩大 mi /d 配 所以直接加即可。

ans = a1 + x*m1 相当于 r1 + xxxx

代码如下 :

#include<iostream>
using namespace std;
typedef long long ll;
const int N = 100010;
int n;
ll ai[N], mi[N];
ll extend_gcd(ll a, ll b, ll& x, ll& y) {
	if (b == 0) { x = 1; y = 0; return a; }
	ll d = extend_gcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}
ll excrt() {
	ll x, y;
	ll m1 = mi[1], a1 = ai[1];
	ll ans = 0; 
	//r = m1*p + r1
	for (int i = 2; i <= n; i++) {
		ll a2 = ai[i], m2 = mi[i];
		ll a = m1, b = m2, c = (a1 - a2); 
		ll d = extend_gcd(a, b, x, y);
		if ( c % d != 0) return -1;
		x = x*c/d;
		x = (x%(m2/d) + m2/d) % (m2 /d);
		ans = a1 + x * m1;
		m1 = m2 / d * m1; // lcm   
		ans = (ans % m1 + m1) % m1;//保证为 正整数  
		a1 = ans;
	}
	return ans;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> mi[i] >> ai[i];
	cout << excrt();
	return 0;
}

时间复杂度为:O(n * 扩展欧几里得算法)

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值