• 「一本通 6.4 例 4」曹冲养猪(CRT)


    复习一下

    扩展中国剩余定理

    • 首先考虑两个同余方程

    [x equiv a_1; mod; m_1\ x equiv a_2; mod; m_2 ]

    • 化成另一个形式

    [x = n_1 * m_1 + a_1\ x = n_2 * m_2 + a_2 ]

    • 联立可得

    [n_1 * m_1 + a_1 = n_2 * m_2 + a_2\ n_1 * m_1 - n_2 * m_2 = a_2 - a_1 ]

    • 有解的前提是

    [gcd(m_1, m_2) |(a_2 - a_1) ]

    [d = gcd(m_1, m_2)\ c = a_2 - a_1 ]

    [n_1 frac{m_1}{d} - n_2 frac{m_2}{d} = frac{c}{d}\ n_1 frac{m_1}{d} equiv frac{c}{d} mod frac{m_2}{d} ]

    • 移项

    [n_1 equiv frac{c}{d} * inv(frac{m_1}{d}, frac{m_2}{d}) mod frac{m_2}{d}\ n_1 = frac{c}{d} * inv(frac{m_1}{d}, frac{m_2}{d}) + y_1 * frac{m_2}{d} ]

    然后(n_1)代入最上面的狮子可以得到

    [x = (frac{c}{d} * inv(frac{m_1}{d}, frac{m_2}{d}) + y_1 * frac{m_2}{d}) * m_1 + a_1\ x = m_1 * frac{c}{d} * inv(frac{m_1}{d}, frac{m_2}{d}) + y_1 * frac{m_2 m_1}{d} + a_1\ x equiv m_1 * frac{c}{d} * inv(frac{m_1}{d}, frac{m_2}{d}) + a_1 mod frac{m_2 m_1}{d} ]

    • 然后就是个新方程了
    • 当然也适用于互质情况
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #define ll long long 
    #define M 22
    #define mmp make_pair
    using namespace std;
    int read()
    {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    
    ll gcd(ll a, ll b)
    {
    	return !b ? a : gcd(b, a % b);
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y)
    {
    	if(!b)
    	{
    		x = 1, y = 0;
    		return a;
    	}
    	else
    	{
    		ll d = exgcd(b, a % b, x, y);
    		ll tmp = x;
    		x = y;
    		y = tmp - a / b * y;
    		return d;
    	}
    }
    
    ll inv(ll a, ll p)
    {
    	ll x, y;
    	ll d = exgcd(a, p, x, y);
    	if(d != 1) return -1;
    	return (x % p + p) % p;
    }
    ll a[M], b[M], n; 
    
    ll excrt()
    {
    	ll a1 = a[1], m1 = b[1], a2, m2;
    	for(int i = 2; i <= n; i++)
    	{
    		a2 = a[i], m2 = b[i];
    		ll c = a2 - a1, d = gcd(m1, m2);
    		if(c % d) return -1;
    		ll k = inv(m1 / d, m2 / d);
    		m2 = m1 / d * m2;
    		a1 = m1 * c / d % m2 * k + a1;
    		m1 = m2;
    		a1 = (a1 % m1 + m1) % m1;			
    	}
    	return a1;
    }
    
    int main()
    {
    	n = read();
    	for(int i = 1; i <= n; i++) b[i] = read(), a[i] = read();
    	cout << excrt() << "
    ";
    	return 0;
    }
    
  • 相关阅读:
    win10补丁导致打印机无法共享
    EdgexGo2.0学习-14 EdgeX2.0 AppService导出到Mqtt
    EdgexGo2.0学习-13 EdgeX2.0 编译Appservice
    winform程序在系统缩放150%时右边留空白问题解决办法
    Linux嵌入式串口转网络
    Win10 磁盘变成文件夹
    Win10下使用Gitblit
    JMeter学习笔记——Web接口测试(webservice)
    jmeter之__RandomFromMultipleVars函数使用详解
    jmeter——参数化——$__RandomFromMultipleVars()函数
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10673305.html
Copyright © 2020-2023  润新知