初学--求解模线性方程组(中国余数定理)。

中国剩余定理,孙子高富帅。

中国剩余定理到求解运用到了扩展欧几里得算法。

求解模线性方程组(中国余数定理)  
   a=B[1](mod W[1])  
   a=B[2](mod W[2])  
   ........  
   a=B[n](mod W[n])  
   
   其中W,B已知,W[i]>0且W[i]与W[j]互质, 求a 

  设m1,m2,…mk是两两互素的正数,则对任意的整数b1,b2,…bk,同余方程组
  x1 = b1 mod m1
  x2 = b2 mod m2
  …
  xk = bk mod mk
  其解为:

  X = (M1’*M1*b1)+(M2’*M2*b2)+…+(Mk’*Mk*bk) mod m;
  其中
  m = m1*m2*…*mk;
  Mi = m / mi;
  Mi’是Mi的逆元

  注意:这个求解的方法到前提是,w[i],w[j]是互质的。

  具体到代码贴一下:(还是比较好理解到)

 

 1 int china(int b[],int m[],int len)
 2 {
 3    int i,d,x,y,mi,sum=1,hxl=0;//好多变量
 4    for(i=1;i<=len;i++)
 5    sum=sum*m[i];//sum=m1*m2*m3*.....mn
 6    for(i=1;i<=len;i++)
 7    {
 8        mi=sum/m[i];//Mi=m/mi
 9        d=Ex_gcd(m[i],mi,x,y);//y是mi的逆元,为什么是y呢,我感到很困惑。
10        hxl=(hxl+mi*y*b[i])%sum;//..
11 } 12 if(hxl>0) 13 return hxl; 14 else 15 return hxl+sum; 16 }

 

  现在的问题是,当w[i] ,w[j] 不互质的时候,怎么去解决。这个也是我们要解决到问题了。

  做到题目里,很少有全部互质到,那就很简单了,直接套模板了,这个你懂了,也是模板。

  如何解决??????

  合并操作.

  先贴一段别人到思路:

                   假设C  A1 (mod B1),C  A2 (mod B2)。令C = A1 + X1B,那么X1B1  A2  A1 (mod B2)。

           用扩展欧几里德算法求出X1,也就求出C。令B = lcm(B1B2),

           那么上面两条方程就可以被C  C (mod B)代替。迭代直到只剩下一条方程。

  有点跳跃性:

  C≡A1 (mod B1)  ==>C=B1*k1 + A1;   //这个容易理解的

  C≡A2 (mod B2)  ==>C=B2*k2 + A2; 

  合并一下  B1*k1 + A1 = B2*k2 + A2  ==>  B1*k1-B2*k2 = A2-A1;

  对比一下扩展欧几里得到式子 ax+by=c ;

  则a=B1 ;  b= -B2;  c=A2-A1;

  根据扩展欧几里得可以求的x0,y0;

  gcd(B1,B2) = d;

  c=A2-A1;

  t=B2/d;          //扩展欧几里得里也有这个  b=b/d;

  x到最小非负解为  x=(x*c/d %t +t)%t;     //需要理解一下。可以分两步 x=x*c/d;  x=(x%t +t )%t;

  那此时就能求出C 了 C=B1*K1 + A1  ==>  C=B1*x + A1;   //就是带入方程,求出C  { C  C (mod B)  }

  B=(B1*B2)/d;    //最小公倍数到求法   b=(b1*b2)/gcd(b1,b2);

  具体到看一看代码。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 __int64 x, y, t;
 7 __int64 egcd(__int64 a, __int64 b)
 8 {
 9     if (b == 0)
10     {
11         x = 1;
12         y = 0;
13         return a;
14     }
15     else
16     {
17         __int64 e = egcd(b, a % b);
18         t = x; x = y; y = t - a / b * y;
19         return e;
20     }
21 }
22 int main()
23 {
24     //freopen("in.txt", "r", stdin);
25     __int64 m1, m2, r1, r2, d, c, t;
26     bool sb;
27     int n;
28     while (cin >> n)
29     {
30         sb = 0;
31         cin >> m1 >> r1;
32         for (int i = 0; i < n - 1; i++)
33         {
34             cin >> m2 >> r2;
35             if (sb) continue;//一旦有无解情况出现,自然就不用在计算了
36             d = egcd(m1, m2);//Ex_gcd(a,b);
37             c = r2 - r1;//ax+by=(c2-c1)   c=c2-c1;//c 是余数
38             if (c % d)//是否有解
39             {
40                 sb = 1;
41                 continue;
42             }
43             t = m2 / d;//b= b/d;
44             x = (c / d * x % t + t) % t;//x=(x0*c/d % b+b)%b;
45                                         //求最小到x
46             r1 = m1 * x + r1;//C = A1 + X1B1 ==> A1=C;
47             m1 = m1 * m2 / d;//最小公倍数赋值给m1  C’ ≡ C (mod B)
48         }
49         if (sb)
50             cout << -1 << endl;
51         else
52             cout << r1 << endl;
53     }
54 
55 }

 

 

 

posted @ 2013-08-15 19:17  芷水  阅读(787)  评论(0编辑  收藏  举报