全程学自y总
 AcWing.204.表达整数的奇怪方式
 给定  
     
      
       
       
         2 
        
       
         n 
        
       
      
        2n 
       
      
    2n 个整数  
     
      
       
       
         a 
        
       
      
        a 
       
      
    a1, 
     
      
       
       
         a 
        
       
      
        a 
       
      
    a2,…, 
     
      
       
       
         a 
        
       
      
        a 
       
      
    an 和  
     
      
       
       
         m 
        
       
      
        m 
       
      
    m1, 
     
      
       
       
         m 
        
       
      
        m 
       
      
    m2,…, 
     
      
       
       
         m 
        
       
      
        m 
       
      
    mn,求一个最小的非负整数  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x,满足  
     
      
       
       
         ∀ 
        
       
         i 
        
       
         ∈ 
        
       
         [ 
        
       
         1 
        
       
         , 
        
       
         n 
        
       
         ] 
        
       
         , 
        
       
         x 
        
       
         ≡ 
        
       
         m 
        
       
      
        ∀i∈[1,n],x≡m 
       
      
    ∀i∈[1,n],x≡mi 
     
      
       
       
         ( 
        
       
         m 
        
       
         o 
        
       
         d 
        
       
         a 
        
       
      
        (mod a 
       
      
    (modai 
     
      
       
       
         ) 
        
       
      
        ) 
       
      
    )。
输入格式
 第 1 行包含整数  
     
      
       
       
         n 
        
       
      
        n 
       
      
    n。
第 2… n n n+1 行:每 i i i+1 行包含两个整数 a a ai 和 m m mi,数之间用空格隔开。
输出格式
 输出最小非负整数  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x,如果  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x 不存在,则输出 −1。
数据范围
  
     
      
       
       
         1 
        
       
         ≤ 
        
       
         a 
        
       
      
        1≤a 
       
      
    1≤ai 
     
      
       
       
         ≤ 
        
       
         231 
        
       
         − 
        
       
         1 
        
       
         , 
        
       
         0 
        
       
         ≤ 
        
       
         m 
        
       
      
        ≤231−1,0≤m 
       
      
    ≤231−1,0≤mi 
     
      
       
       
         < 
        
       
         a 
        
       
      
        <a 
       
      
    <ai
  
     
      
       
       
         1 
        
       
         ≤ 
        
       
         n 
        
       
         ≤ 
        
       
         25 
        
       
      
        1≤n≤25 
       
      
    1≤n≤25
 所有  
     
      
       
       
         m 
        
       
      
        m 
       
      
    mi 的最小公倍数在  
     
      
       
       
         64 
        
       
      
        64 
       
      
    64 位有符号整数范围内。
输入样例:
8 7
11 9
输出样例:
31
中国剩余定理:
 以 
     
      
       
       
         M 
        
       
         = 
        
       
         m 
        
       
      
        M=m 
       
      
    M=m1 
     
      
       
       
         ∗ 
        
       
         m 
        
       
      
        *m 
       
      
    ∗m2 
     
      
       
       
         ∗ 
        
       
         . 
        
       
         . 
        
       
         . 
        
       
         m 
        
       
      
        *...m 
       
      
    ∗...mk。
以 M M Mi = = = M m i \frac{M}{m~i~} m i M。即Mi表示除了mi之外其他所有m的乘积,则Mi和mi是互质的,则我们可以求出 M M Mi m o d m modm modmi的逆元
用Mi-1表示 M M Mi m o d m modm modmi的逆元,逆元即 a ∗ x ≡ 1 ( m o d m ) a*x ≡ 1(modm) a∗x≡1(modm),即我们可以通过扩展欧几里得算法来求出逆元
则 x = a x = a x=a1 ∗ M *M ∗M1 ∗ M *M ∗M1-1 + a +a +a2 ∗ M *M ∗M2 ∗ M *M ∗M22 + + +… a a an ∗ M *M ∗Mn ∗ M *M ∗Mn-1。此式子得到的 x x x就是解
对于此道题:我们现在有很多个方程(x mod ai = mi),需要在每一步去合并方程
 过程如下:
 
 代码如下:
#include<iostream>
using namespace std;
#define ll long long
ll exgcd(ll a, ll b, ll &x, ll &y) {	//扩展欧几里得算法
	if (!b) {
		x = 1, y = 0;
		return a;
	}
	ll d = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}
int main() {
	int n; cin >> n;
	bool has_answer = 1;	//判断是否有解
	ll a1, m1;
	cin >> a1 >> m1;	//第一个方程的a1和m1
	for (int i = 0; i < n - 1; i++) {	//要合并n-1次方程
		ll a2, m2;
		cin >> a2 >> m2;//第二个方程的a2和m2
		ll k1, k2;		//要求的系数
		ll d = exgcd(a1,a2,k1,k2);	//求最大公约数同时求出了系数
		
		if ((m2 - m1) % d) {	//如果m2-m1和最大公约数不成倍数,那么无解
			has_answer = 0;
			break;
		}
		//此时求出的d为k1*a1 - k2*a2的最大公约数,而我们要求相对于m2-m1的
		//则需把求出的k1,k2乘上m2-m1 / d
		k1 *= (m2 - m1) / d;	//更新k1
		ll t = a2 / d;
		k1 = (k1 % t + t) % t;	//在k1的众多解中,取出最小的那个
		m1 = a1 * k1 + m1;		//更新m1,以进行下次合并方城
		a1 = abs(a1 / d * a2);	//更新a1
	}
	if (has_answer) {
		cout << (m1 % a1 + a1) % a1 << endl; //保证负数时求出正确的模数,上面t同理(C++直接模会与数学结果不同)
	}
	else {
		cout << -1 << endl;
	}
	return 0;
}



















