poj 2891 扩展欧几里得解一元线性同余方程组

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 }
View Code

 

posted @ 2015-11-02 19:32  lmlyzxiao  阅读(1240)  评论(0编辑  收藏  举报