博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模线性同余方程组求解
阅读量:5008 次
发布时间:2019-06-12

本文共 3445 字,大约阅读时间需要 11 分钟。

问题:模线性同余方程组:

  x = a1 ( mod n1 )

  x = a2 ( mod n2 )

    ....

  x = ak ( mod nk )

给定 A ( a1, a2 , ... , ak ) , N ( n1, n2, ..., nk ) 求 X 。

 

通常分为两种

  一, ( Ni, Nj ) 之间两两互质

  二, ( Ni, Nj ) 之间不都互质

 

 

一 ( Ni, Nj ) 之间两两互质

  定理( 见算法导论 P874 ):

  如果 n1, n2 , ... , nk 两两互质, n = n1*n2*..*nk ,则对任意整数 a1,a2,a3..,ak , 方程组

    x = ai ( mod ni )

  关于未知量 x 对 模n 有唯一解

 

从输入 ( a1, a2, ... , ak ) 计算出 a :

       

    定义   

    定义  

可以得到:

     

 

代码模板

  a = a[i] ( mod n[i] )   ( i = 0. 1. 2. .. k )       {  n[i] 之间两两互质 }

View Code
#include
#include
#include
#include
#include
using namespace std;typedef long long LL;const int N = 1010;LL a[N], n[N], nn, k;LL Exgcd( LL a, LL b, LL &x, LL &y ){ if( b == 0 ){ x = 1; y = 0; return a; } LL r = Exgcd( b, a%b, x, y ); LL t = x; x = y; y = t - a/b*y; return r;}LL mul( LL a, LL b ){ LL res = 0; while( b ) { if( b&1 ) if( (res+=a) >= nn ) res -= nn; a <<= 1; if( a >= nn ) a -= nn; b >>= 1; } return res;}LL inverse( LL A, LL B ){//求逆元 LL x, y; Exgcd( A, B, x, y ); return (x%B+B)%B;}LL China(){ scanf("%lld", &k); // k个 模同余等式 for(int i = 0; i < k; i++) scanf("%lld", &a[i] ); for(int i = 0; i < k; i++) scanf("%lld", &n[i] ); nn = 1; for(int i = 0; i < k; i++) nn *= n[i]; LL A = 0; for(int i = 0; i < k; i++) { // ci = mi * (mi^-1 mod ni ) // ai * ci LL m = nn/n[i], m1 = inverse( m, n[i] ); LL c = m*m1; A = ( A + mul( a[i], c ) ) % nn; } return A;}int main(){ printf("%lld\n",China() ); return 0;}

 

二( Ni, Nj ) 之间不都互质  

  

    x = ai ( mod mi )  1 <= i <= k

    先考虑k==2的情况:

      x = a1 ( mod m1 )

      x = a2 ( mod m2 )

   方程组有解的充分必要条件是: d | (a1-a2) ,其中 d = (m1,m2)

 

证明如下:

    必要性:

        设 x 是上面同余方程组的解,从而存在整数q1,q2使得x=a1+m1*q1,x=a2+m2*q2,消去x即得a1-a2 = m2q2-m1q1。由于d= GCD(m1,m2),故d | (a1-a2)。

    充分性:

        若d=GCD(m1,m2) | (a1-a2)成立,则方程m1*x + m2*y = a1-a2有解。

        设解为x0,y0。那么m2*y0 = a1-a2 ( mod m1 )

        记x1 = a2+m2*y0,可以知道 x1=a2 ( mod m2 ),且x1 = a2+m2*y0 = a2 + ( a1-a2) = a1 ( mod m1 )

        所以 x1 = a2 ( mod m2 ) = a1 ( mod m1 ) 

        所以 x = x1 ( mod GCD[m1,m2] ) 

        另外,若x1与x2都是上面同余方程组的解,则 x1 = x2 ( mod m1 ), x1 = x2 ( mod m2 ),

        由同余的性质得 x1 = x2 ( mod [m1,m2] ),即对于模[m1,m2],同余方程组的解释唯一的。

    证毕。

C++代码模板:

  

#include
typedef long long LL;LL ExGcd( LL a, LL b, LL &x, LL &y ){ if( b == 0 ) { x=1;y=0; return a; } LL r = ExGcd( b, a%b, x, y ); LL t = x; x = y; y = t - a/b*y; return r;}LL Modline( LL r[], LL a[], int n ){ // X = r[i] ( mod a[i] ) LL rr = r[0], aa = a[0]; for(int i = 1; i < n; i++ ) { // aa*x + a[i]*y = ( r[i] - rr ); LL C = r[i] - rr, x, y; LL d = ExGcd( aa, a[i], x, y ); if( (C%d) != 0 ) return -1; LL Mod = a[i]/d; x = ( ( x*(C/d)% Mod ) + Mod ) % Mod; rr = rr + aa*x; // 余数累加 aa = aa*a[i]/d; // n = n1*n2*...*nk } return rr;}// test int main(){ int n; LL r[10], a[10]; while( scanf("%d", &n) != EOF) { for(int i = 0; i < n; i++) scanf("%lld", &r[i] ); for(int i = 0; i < n; i++) scanf("%lld", &a[i] ); printf("%lld\n", Modline( r, a, n ) ); } return 0;}

 

转载于:https://www.cnblogs.com/yefeng1627/archive/2012/12/31/2841058.html

你可能感兴趣的文章
JSON解析
查看>>
Position is everything?(css定位学习的一些心得)(一)
查看>>
如何提高编程水平
查看>>
Jquery Uploadify3.21.与2.1版本 使用中存在的问题--记录三
查看>>
Linux查看进程的内存占用情况 分类: ubuntu ...
查看>>
[BZOJ 2818]Gcd
查看>>
FORM值传递与地址传递
查看>>
(译)yaml快速教程
查看>>
C:大数相加
查看>>
静态博客教程 1:hexo + github
查看>>
160. Intersection of Two Linked Lists
查看>>
人生苦短,我用python-- Day11
查看>>
JAVA Bean
查看>>
ehcache memcache redis 三大缓存男高音_转
查看>>
需求文档
查看>>
JVM GC(整理)
查看>>
基于select的socket编程
查看>>
Servlet(二)
查看>>
对APS的简单了解
查看>>
curd_3
查看>>