http://poj.org/problem?id=2891
题意:
选择K个不同的正整数a1,a2.....ak,对于某个整数m分别对ai求余对应整数ri,如果当选择a1,a2,....ak,那么m可由整数对组合(ai,ri)唯一确定。
现在已知a1,a2,...ak以及所有的整数对(ai,ri)求最小的非负整数m的值。
设 a,b为整数,且a(!Ξ)0(mod)m,则称同余方程 ax Ξ b(mod)m为一次同余方程
一次同余方程的求解步骤
1:求gcd(a,m)
2:令d = gcd(a,m) 如果d不能整除b则无解,否则转3
3:根据ex_gcd 求得一个解x0;
用扩展欧几里得求解的具体做法如下:
(1):用ex_gcd求得满足 ax' + my' = d 的x'和y'。具体方法是将 ax'+my' = d 变形可以得到 ax' = d - my';
对变形后的式子两边同时取模m得 ax'Ξd(mod)m,至此可见x'是同余方程的解
(2):根据x'求x0。具体方法是:由于d能整除b 设 p = b/d,则根据同余式的性质得到:a(px')≡dp(mod)m即:a(px')≡b(mod)m.因此x0 = px' = b/d*x'(mod)m.
4:根据求得的x0可以得到其他d-1个解为 xi = (x0 + i*m/d)(mod)m, i = 1,2,...d-1.
然后根据上面的方法去解上面的题。代码是求得方程组小于m的非负整数解。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <stack> 5 #include <queue> 6 #include <map> 7 #include <algorithm> 8 #include <vector> 9 10 using namespace std; 11 12 const int maxn = 1000005; 13 14 typedef long long LL; 15 16 LL ex_gcd(LL a,LL b,LL &x,LL &y) 17 { 18 if(b == 0){ 19 x = 1; 20 y = 0; 21 return a; 22 } 23 LL r = ex_gcd(b,a%b,x,y); 24 LL t = x; 25 x = y; 26 y = t - a/b*y; 27 return r; 28 } 29 int main() 30 { 31 LL i,n,a1,r1,a2,r2,ans,a,b,c,d,x0,y0; 32 while(scanf("%lld",&n)!=EOF){ 33 bool flag = 1; 34 scanf("%lld%lld",&a1,&r1); 35 for( i=1;i<n;i++){ 36 scanf("%lld%lld",&a2,&r2); 37 a = a1; 38 b = a2; 39 c = r2-r1; 40 LL d = ex_gcd(a,b,x0,y0); 41 if(c%d!=0){ 42 flag = 0; 43 } 44 int t = b/d; 45 x0 = (x0*(c/d)%t+t)%t;//保证x0为正 46 r1 = a1*x0 + r1; 47 a1 = a1*(a2/d); 48 49 50 } 51 if(!flag){ 52 puts("-1"); 53 continue; 54 } 55 printf("%lld\n",r1); 56 } 57 return 0; 58 }