//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 ;
}
模线性方程组
最新推荐文章于 2021-01-01 15:47:53 发布