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 * 扩展欧几里得算法)

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-03 16:32:07       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-03 16:32:07       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-03 16:32:07       82 阅读
  4. Python语言-面向对象

    2024-04-03 16:32:07       91 阅读

热门阅读

  1. 【PostgreSQL】postgresql触发OOM解析

    2024-04-03 16:32:07       31 阅读
  2. 2.docker 镜像相关命令

    2024-04-03 16:32:07       38 阅读
  3. springboot Guacamole

    2024-04-03 16:32:07       29 阅读
  4. 回溯算法C实现

    2024-04-03 16:32:07       44 阅读
  5. 关于自动化测试工具RobotFrameWork

    2024-04-03 16:32:07       37 阅读
  6. React 优先级队列小顶堆的简单实现

    2024-04-03 16:32:07       42 阅读
  7. Rust语言中Option和Result两种类型的使用

    2024-04-03 16:32:07       39 阅读
  8. js 模块化

    2024-04-03 16:32:07       37 阅读