模线性方程组

//POJ2891
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<algorithm>
using namespace std ;


typedef long long ll ;
const int maxn = 1e6 + 10 ;


ll m [maxn ] , r[maxn] ;

/*
模线性方程组
问题: 对于一组除数m[i] , 余数r[i] , 求一个数x是的 x%m[i] = r[i] 恒成立
原理: 对于模线性方程组  x % M = R     
                        ...
                        x % m[i] = r[i] 
      有 x = M * k1 + R                    方程一 
         x = m[i] * k2 + r[i]              方程二 

      则M * k1 + R = m[i] * k2 + r[i]
      则 M * k1 - m[i] * k2 = r[i] - R      ---公式1 
      根据    扩展欧几里得求出 k1 的特解为 ( c/d * k1 )
      在 方程一种为了取x最小  k1 = ( c/d * k1 ) % ( m[i] / d) 
      则 x的特解  = (  R = R + k1 * M   ) 

      根据方程一和二求得 x通解 X = x + lcm( M , m[i] ) * k 

      则 M =  lcm( M , m[i] )
      X = ( R = R% M ) 

复杂度: O(n*logmax( a, b)) ? 
应用:求同余方程组的解

*/

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

ll MSLE(ll a ){
    ll M = m[0] , R = r[0] ;
    for(int i = 1 ;i< a ;i++){
        ll k1 , k2 ;
        ll d = extgcd( M , m[i] , k1 , k2) ;
        ll c = r[i] - R ;
        if( c %d ) return -1 ;
        k1 = ( c/d * k1 ) % ( m[i] / d) ;
        R = R + k1 * M ;
        M = M/d* m[i] ;
        R = R % M  ;
    } 
    if( R < 0 )
        R += M ;
    return R ;
}

int main(){
    int a ;
    while(cin>>a){
        for(int i = 0 ;i< a ;i++){
            cin>>m[i]>>r[i] ; 
        }
        ll ans = MSLE(a) ;

        cout<<ans<<endl;
    }
    return 0 ;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值