天天看点

Acwing 204. 表达整数的奇怪方式(扩展中国剩余定理)Acwing 204. 表达整数的奇怪方式(扩展中国剩余定理)

Acwing 204. 表达整数的奇怪方式(扩展中国剩余定理)

Acwing 204. 表达整数的奇怪方式(扩展中国剩余定理)Acwing 204. 表达整数的奇怪方式(扩展中国剩余定理)

解题步骤:

扩展中国剩余定理的模板题

x ≡ m 1 ( m o d   a 1 ) x\equiv m_1(mod \ a_1) x≡m1​(mod a1​)

x ≡ m 2 ( m o d   a 2 ) x\equiv m_2(mod \ a_2) x≡m2​(mod a2​)

⇒ a 1 ∗ y 1 + m 1 = a 2 ∗ y 2 + m 2 \Rightarrow a_1 * y_1 + m_1 = a_2 * y_2 + m2 ⇒a1​∗y1​+m1​=a2​∗y2​+m2

⇒ y 1 ∗ a 1 − y 2 ∗ a 2 = m 2 − m 1 \Rightarrow y_1 * a_1 - y_2 * a_2 = m_2 - m_1 ⇒y1​∗a1​−y2​∗a2​=m2​−m1​

Y 1 ∗ a 1 + Y 2 ∗ a 2 = g c d ( a 1 , a 2 ) Y_1 * a_1 + Y_2 * a_2 = gcd(a_1,a_2) Y1​∗a1​+Y2​∗a2​=gcd(a1​,a2​)

当 ( m 2 − m 1 )   %   g c d ( a 1 , a 2 )   ! = 0 (m_2 - m_1) \ \%\ gcd(a_1,a_2) \ != 0 (m2​−m1​) % gcd(a1​,a2​) !=0 时无解

若有解

y 1 = Y 1 ∗ (   ( m 2 − m 1 ) / g c d ( a 1 , a 2 )   ) + t ∗ a 2 / g c d ( a 1 , a 2 ) y_1 = Y_1*(\ (m_2-m_1)/gcd(a_1,a_2)\ ) + t * a_2 / gcd(a_1,a_2) y1​=Y1​∗( (m2​−m1​)/gcd(a1​,a2​) )+t∗a2​/gcd(a1​,a2​)​

x ≡ m 1 ( m o d   a 1 ) ⇒ x = y 1 ∗ a 1 + m 1 x\equiv m_1(mod \ a_1) \Rightarrow x = y_1 * a_1 + m_1 x≡m1​(mod a1​)⇒x=y1​∗a1​+m1​

x = ( Y 1 ∗ (   ( m 2 − m 1 ) / g c d ( a 1 , a 2 )   ) + t ∗ a 2 / g c d ( a 1 , a 2 ) ) ∗ a 1 + m 1 x = \left(Y_1*\left(\ \left(m_2-m_1\right)/gcd\left(a_1,a_2)\ \right) + t * a_2 / gcd(a_1,a_2\right) \right)*a_1 + m_1 x=(Y1​∗( (m2​−m1​)/gcd(a1​,a2​) )+t∗a2​/gcd(a1​,a2​))∗a1​+m1​

= Y 1 ∗ (   ( m 2 − m 1 ) / g c d ( a 1 , a 2 )   ) ∗ a 1 + m 1 ⏟ 新 的 m 1 + t ∗ l c m ( a 1 , a 2 ) ⏟ 新 的 a 1 =\underbrace{Y_1*(\ (m_2-m_1)/gcd(a_1,a_2)\ ) * a_1 + m_1 }_{新的m_1} + t * \underbrace{lcm(a_1,a_2)}_{新的a_1} =新的m1​

Y1​∗( (m2​−m1​)/gcd(a1​,a2​) )∗a1​+m1​​​+t∗新的a1​

lcm(a1​,a2​)​​

每次更新 a 1 , m 1 a_1,m_1 a1​,m1​ 和新读入的 a 1 , m 2 a_1,m_2 a1​,m2​ 进行运算

最终得到结果 x = ( m 1   %   a 1 + a 1 ) % a 1 ) x = (m_1\ \% \ a_1 + a_1 ) \% a_1 ) x=(m1​ % a1​+a1​)%a1​)​​

AC代码

#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long ll; 
using namespace std;
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 ;
    scanf("%d",&n) ; 
    ll a1 , m1 ;
    scanf("%lld%lld",&a1,&m1) ; 
    int flag = 1 ; 
    for(int i = 1 ; i < n ; i ++ ) {
        ll a2 , m2 , y1 , y2 ; 
        scanf("%lld%lld",&a2,&m2) ; 
        ll d = exgcd(a1,a2,y1,y2) ; 
        if( (m2 - m1 ) % d ) {
            flag = 0 ;
            break;
        }
        y1 = y1 * ( m2 - m1 ) / d ; 
        ll t = a2 / d ; 
        y1 = ((y1 % t) + t ) % t ; 
        m1 = y1 * a1 + m1 ; 
        a1 = a1 * a2 / d;  
    }
    if(flag){
        printf("%lld", (m1 % a1 + a1 ) % a1 ) ; 
    }
    else puts("-1") ; 
    return 0 ; 
}