NOIp提高组 2012 同余方程

同余:数论中的重要概念。给定一个正整数m,如果两个整数a和b满足(a-b)能够整除m,即(a-b)/m得到一个整数,

那么就称整数a与b对模m同余,记作a≡b(mod m)。对模m同余是整数的一个等价关系。

数学上同余,两个整数除以同一个整数,若得相同余数,则二整数同余。

两个整数a、b,若它们除以整数m所得的余数相等,则称a与b对于模m同余或a同余于b模m

记作 a≡b (mod m)

读作 a同余于b模m,或读作a与b对模m同余。

例如 26≡2 (mod 12)

【定义】设m是大于1的正整数,a、b是整数,如果m|(a-b),则称a与b关于模m同余,记作a≡b(mod m),读作a与b对模m同余.

显然,有如下事实

(1)若a≡0(mod m),则m|a;

(2)a≡b(mod m)等价于a与b分别用m去除,余数相同。

【证明】

充分性: m|(a-b)——> a≡b(mod m)

设a=mq1+r1,b=mq2+r2

且0≤r1,r2<m

∵ m|(a-b)

又a-b=m(q1-q2)+(r1-r2).

∴必有常数n使得(r1-r2)=mn

则有m|(r1-r2).

∵0≤r1,r2<m,

∴0≤|r1-r2|<m

∴r1-r2=0

即r1=r2.

故a≡b(mod m).

必要性:a≡b(mod m)——>m|(a-b)

设a,b用m去除余数为r,

即a=mq1+r,b=mq2+r.

∵a-b=m(q1-q2)

∴m|(a-b).

同余的性质也比较多,主要有以下一些:

1.对于同一个除数,两个数之和(或差)与它们的余数之和(或差)同余。

2.对于同一个除数,两个数的乘积与它们余数的乘积同余。

3.对于同一个除数,如果有两个整数同余,那么它们的差就一定能被这个除数整除。

4.对于同一个除数,如果两个数同余,那么他们的乘方仍然同余。

同余的应用:

例题:求2001^2003除以13的余数

根据同余性质4,我们可以得出20012003≡122003(mod 13) (2001和12模13同余)

12^2003还是一个较大的数,很难求出它除以13的余数,这时,我们就要找出12的几次方与1对于模13是同余的。

根据试验,可得出12^2≡1(mod 13)

我们把12^2003拆成 (122)1001×12^1,而 (122)1001×12^1≡1×12≡12(mod 13)

这时,我们可以得出2001^2003除以13的余数为12,我们用计算器计算一下,这个答案是对的。

在数论中,线性同余方程是最基本的同余方程,“线性”表示方程的未知数次数是一次,即形如:

ax≡b (mod n)的方程。此方程有解当且仅当 b 能够被 a 与 n 的最大公约数整除(记作 gcd(a,n) | b)。

这时,如果 x0 是方程的一个解,那么所有的解可以表示为:

{ x0+kn/d | (k∈z) }

其中 d 是a 与 n 的最大公约数。在模 n 的完全剩余系 {0,1,…,n-1} 中,恰有 d 个解。

对于线性同余方程 ax ≡ b (mod n) (1)

若 d = gcd(a, n),d 整除 b ,那么b/d为整数。由裴蜀定理,存在整数对 (r,s) 可用辗转相除法使得 ar+sn=d,

因此 x0=rb/d是方程 (1) 的一个解。其他的解都关于n/d与 x 同余。即x≡x0+(n/d)*t (mod n) (0≤t≤d-1)。

举例来说,方程12x ≡ 20 (mod 28)中 d = gcd(12,28) = 4 。

注意到 4 = 12 (-2)+281,因此 x0≡5*(-2) ≡-10 ≡4(mod 7)是一个解。

对模 28 来说,t=1,x≡4+(28/4)*1≡11 (mod 28);

       t=2,x≡4+(28/4)*2≡18 (mod 28);

   t=3,x≡4+(28/4)*3≡25 (mod 28) 。

所有的解就是 {4,11,18,25} 。

求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。

即求ax=mb+r 1=nb+r

变形ax+(n-m)b=1,此方程即拓展欧几里德的应用ax+by=gcd(a,b),(n-m相当于y)

事实上ax ≡1(mod b) 有解的必要条件是gcd(a,b)|1,即gcd(a,b)=1;

使用拓展欧几里得可知 ax+by=1(x,y是整数)

扩展欧几里得定理

扩展欧几里得定理:对于两个不全为0的整数a、b,必存在一组解x,y,使得ax+by==gcd(a,b);

拓展欧几里得实现,下面的程序中,x和y用全局变量保存

int gcd(int a,int b)
{
int t,d;
if(b0)
{
x=1;
y=0;
//此时b
0,也就是说gcd(a,0)a。原式变为ax+bya=gcd(a,b)--> x1,y0
return a; //返回a,b最大公约数的值
}
d=gcd(b,a%b); //欧几里得求最大公约数应用
t=x;
x=y;
y=t-(a/b)*y; //不明处2
return d; //返回a,b最大公约数的值
}
//不明处2 解释 ax+by==gcd(a,b)(1)
说明规则,x,y表示第一次递归时的值,x1,y1表示第二次递归时的值。

那么gcd(a,b)==gcd(b,a%b),同时都代入式1,

有ax+by==bx1+(a%b)y1。将右边变形一下

bx1+(a%b)y1bx1+(a-(a/b)b)y1ay1+b(x1-(a/b)y1),

最终得到ax+by==ay1+b(x1-(a/b)*y1)

也就是说:

上一深度的x等于下一深度的y1,

上一深度的y等于下一深度的x1-(a/b)*y1。

*需要注意,上面推导时用的除法都是整型除法

因此,得到了不定式ax+by==gcd(a,b)的一组解,x、y。

那么对于一般的不定式ax+by==c,它的解应该是什么呢。

很简单,x1=x(c/gcd(a,b)),y1=y(c/gcd(a,b))

再深入一点,就解出这么一组解其实一般来说是解决不了什么问题的,

我们现在要得到所有的解,那么这所有的解究竟是什么呢?

假设d=gcd(a,b). 那么x=x0+b/dt; y=y0-a/dt;其中t为任意常整数。

代码如下:

#include<stdio.h>
int  Extragcd(int a,int b,int *x,int *y)
{
	int d,t;
	if(b==0)  //递归调用终止条件,当根据欧几里得辗转相除法则,余数为0停止
	{
		*x=1;
		*y=0;
		return a;
	}
	else
	{
		d=Extragcd(b,a%b,x,y);
		t=*x;                  //根据下一个x1,y1的值,倒推前一个x,y的值
		*x=*y;
		*y=t-a/b*(*y);
		return d;
	}
}
int main()
{
	int a,b,x,y;
	int ans;
	scanf("%d%d",&a,&b);
	ans=Extragcd(a,b,&x,&y);   //同余方程 ax ≡1 (mod b) 有解的充分条件是 gcd(a,b)==1
	if(ans!=1) return 0;
	                          //根据若x是方程的一个解,则方程的所有解为x+k*b k为整数
    x=x%b;                    //保证最小的正整数解x ,且x属于{0,1,2,3...b-1}
    while(x<=0)
        x+=b ;
    printf("%d
",x);
    return 0;
}
原文地址:https://www.cnblogs.com/zi-nai-boboyang/p/11519409.html