线性同余方程与中国剩余定理

【线性同余方程】

1.定义

给定整数 a , c , m a,c,m ,求一个整数 x x 满足 a x c   ( m o d   m ) a*x \equiv c\ (mod\ m) ,或者给出无解。因为未知数的指数为 1 1 ,所以我们称之为一次同余方程,也称线性同余方程。

2.过程分析

a x c   ( m o d   m ) a*x \equiv c\ (mod \ m) 等价于 a x c a*x-c m m 的倍数,不妨设为 y -y 倍。于是,该方程可以改写为 a x + m y = c a*x+m*y=c

我们先用扩展欧几里德算法求出 a x + m y = g c d ( a , m ) ax+my=gcd(a,m) 一组解 x 0 y 0 x_0、y_0

对于方程 a x + m y = c a*x+m*y=c ,它存在解的充要条件 c % g c d ( a , m ) = = 0 c\%gcd(a,m)==0 ,且它的一组解 ( x , y ) (x,y) 等于 ( c x 0 g c d ( a , m ) , c y 0 g c d ( a , m ) ) (\frac{cx_0}{gcd(a,m)},\frac{cy_0}{gcd(a,m)})

事实上,若方程 a x + m y = c ax+my=c 有整数解,则共有 g c d ( a , m ) gcd(a, m) 个解,其全部解的公式为:
{ x = c x 0 g c d ( a , m ) + m g c d ( a , m ) K y = c y 0 g c d ( a , m ) a g c d ( a , m ) K   ( K ) \left\{\begin{matrix}x=\frac{cx_0}{gcd(a,m)}+\frac{m}{gcd(a,m)}*K \\ y=\frac{cy_0}{gcd(a,m)}- \frac{a}{gcd(a,m)}*K \end{matrix}\right. \ (K为任意整数)

3.结论

a , c , m a, c,m 是整数,其中 m 1 m \geq 1 ,则

(1)若 c % g c d ( a , m ) 0 c\%gcd(a,m) \neq 0 ,则方程 a x c   ( m o d   m ) ax \equiv c\ (mod \ m) 无解

(2)若 c % g c d ( a , m ) = 0 c\%gcd(a,m) = 0 ,则方程 a x c   ( m o d   m ) ax \equiv c\ (mod \ m) 恰好有 g c d ( a , m ) gcd(a,m) 个模 m m 意义下不同的解,且解的形式为
x = x + m g c d ( a , m ) K x'=x+\frac{m}{gcd(a,m)}*K
其中 K = 0 , 1 , . . . , g c d ( a , m ) 1 K=0,1,..., gcd(a,m)-1 x x a x + m y = c ax+my=c 的一个解。

4.实现

综上分析,可以使用扩展欧几里德算法求线性同余方程的一组解。

实际上,常常被要求去求最小的正整数的解,先通过扩展欧几里德算法求出方程的一组 x 0 y 0 x_0、y_0 ,再设 t = b / G C D ( a , b ) t=b/GCD(a,b) 来拓展方程的解,调整 x x 的范围,将 a x 0 + b y 0 = c a*x_0+b*y_0=c 拓展为 a ( x 0 + t k ) + b ( y 0 t k ) = c , k Z a*(x_0+t*k)+b*(y_0-t*k)=c,k \in Z ,从而使得所得到的 x x 尽可能的小,通过式子 x = ( x    m o d    t + t )    m o d    t x=(x\:\, mod\:\, t+t)\:\,mod\:\,t 来约束结果一定是一个正数,最后所得到的 x x 即是一个最小的正整数解。

#include<iostream>
using namespace std;
int Extended_GCD(int a, int b, int &x, int &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }
 
    int temp;
    int gcd = Extended_GCD(b,a%b,y,x);
    y -= x*(a/b);
    return gcd;
}

int main()
{
    //形如 ax+by=c
    int a, b, c, x, y;
    cin>>a>>b>>c;
 
    int gcd = Extended_GCD(a, b, x, y);
    if(c%gcd!=0)
        cout<<"无整数解"<<endl;
    else
        cout<<"该方程的一组整数解为:x="<<x*c/gcd<<",y="<<y*c/gcd<<endl;
 
	return 0;
}

【中国剩余定理】

1.定义

线性同余方程组是由若干个线性同余方程构成的线性方程组,其解法最早由我国《孙子算经》给出,因此解法称为“孙子定理”,又叫“中国剩余定理”,实质即为求多个数的最小公倍数。

2.内容

{ x a 1 ( m o d m 1 ) x a 2 ( m o d m 2 ) . . . x a n ( m o d m n ) \left\{\begin{matrix}x\equiv a_1(mod\:m_1) \\ x\equiv a_2(mod\:m_2) \\ ... \\x\equiv a_n(mod\:m_n) \end{matrix}\right.

设自然数 m 1 , m 2 , . . . , m n m_1,m_2,...,m_n 两两互质,并记 m = m 1 m 2 . . . m n m=m_1*m_2*...*m_n ,记 M i = m m i M_i=\frac{m}{m_i} ,记 t i t_i 表示 M i M_i m i m_i 的逆(即 t i t_i 是线性同余方程 M i t i 1   ( m o d   m i ) M_it_i \equiv 1\ (mod\ m_i) 的一个解)

那么,对于任意的 n n 个整数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n ,方程组有整数解,解为
x = a 1 M 1 t 1 + a 2 M 2 t 2 + . . . + a n M n t n = i = 1 n a i M i t i x = a_1M_1t_1+a_2M_2t_2+...+a_nM_nt_n=\sum\limits_{i=1}^{n}a_iM_it_i

3.实现

#include<iostream>
using namespace std;

int Extended_GCD(int a, int b, int &x, int &y)
{
    if(b==0)
	{
        x = 1;
        y = 0;
        return a;
    }
 
    int gcd = Extended_GCD(b, a%b, y, x);
    y = y - a/b*x;
    return gcd;
}

int China(int W[], int B[], int k)		//W除数,B余数
{
    int mod = 1;
    for(int i = 0; i < k; i++)			//计算mod的大小
        mod *= W[i];
 
    int res = 0;
    int x, y, m;
    for(int i = 0; i < k; i++)
	{
        m = mod / W[i];
        Extended_GCD(W[i], m, x, y);		//求出每一组W[i]与m的解
        res = (res + y * B[i] * mod / W[i] + mod) % mod;	//累加所有解
    }
    return (res + mod) % mod;
}

中国剩余定理给出了模数两两互质的线性同余方程组的一个特解。

方程组的通解可以表示为 x + k m   ( k Z ) x+km \ (k∈Z) 。有些题目要求我们求出最小的非负整数解,只需把 x x m m 取模,并让 x x 落在 0 m 1 0 \sim m-1 的范围内即可。

发布了811 篇原创文章 · 获赞 127 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104795049
今日推荐