定义: 同余给定正整数 m m m,若用 m m m去除两个整数 a a a和 b b b,所得的余数相同,称a和b对模 m m m同余,记作 a ≡ b ( m o d m ) a≡b(mod\ m) a≡b(mod m),并称该式为同余式,否则,称 a a a和 b b b对模 m m m不同余。
定理:
定义:由与同余关系是等价关系,对于所有整数会被分为 m m m的集合,这些集合称为模 m m m剩余类(同余类)。每个集合中的任意两个数都是模 m m m同余的。
定义:一个整数集合,且满足对于任意的整数在此集合中存在一个元素与该整数模 m m m同余,该整数 0 , 1 , 2 , . . . , m − 1 0,1,2,... ,m-1 0,1,2,...,m−1的集合是模 m m m的完全剩余系。
定理:若 a a a, b b b, c c c, d d d是整数, m m m是正整数,且 a ≡ b ( m o d m ) , c ≡ d ( m o d m ) a≡b(mod\ m),c≡d(mod\ m) a≡b(mod m),c≡d(mod m),则:
4. a + b ≡ b + c ( m o d m ) a+b≡b+c(mod\ m) a+b≡b+c(mod m)
5. a − b ≡ b − c ( m o d m ) a-b≡b-c(mod\ m) a−b≡b−c(mod m)
6. a c ≡ b c ( m o d m ) ac≡bc(mod\ m) ac≡bc(mod m)
7. a c ≡ b c ( m o d m ) , c ≠ 0 ac≡bc(mod\ m),c≠0 ac≡bc(mod m),c=0,则 a ≡ b ( m o d m g c d ( m , c ) ) a≡b(mod\ \frac{m}{gcd(m,c)}) a≡b(mod gcd(m,c)m)
8. a x + c y = b x + d y ( m o d m ) ax+cy=bx+dy(mod\ m) ax+cy=bx+dy(mod m),其中 x , y x,y x,y为任意整数,即同余式可以相加
9. a c ≡ b d ( m o d m ) ac≡bd(mod\ m) ac≡bd(mod m),即同余式可以相乘
10. a n ≡ b n a^n≡b^n an≡bn, n > 0 n>0 n>0
11. f ( a ) ≡ f ( b ) ( m o d m ) f(a)≡f(b)(mod\ m) f(a)≡f(b)(mod m),其中 f ( x ) f(x) f(x)为任一整数多项式
定理:若a,b,c,d为整数,m为正整数,则:
证明上式1, 若 a ≡ b ( m o d m ) a≡b(mod\ m) a≡b(mod m) ,则 a x ≡ b x ( m o d m ) ax≡bx(mod\ m) ax≡bx(mod m),令 x d = m xd=m xd=m,两边同除 x x x, a ≡ b ( m o d m g c d ( m , x ) ) a≡b(mod\ \frac{m}{gcd(m,x)}) a≡b(mod gcd(m,x)m), g c d ( m , x ) = x gcd(m,x)=x gcd(m,x)=x,即 a ≡ b ( m o d d ) a≡b(mod\ d) a≡b(mod d)
证明上式2,若 d d d为 a a a和 m m m的公约数,且 m ∣ ( a − b ) , d ∣ a , d ∣ m m|(a-b),d|a,d|m m∣(a−b),d∣a,d∣m,所以 d ∣ b d|b d∣b,对于所有 d d d上式都成立,反之亦然成立,即 a a a与 m m m和 b b b与 m m m的公约数集相同,所以 ( a , m ) = ( b , m ) (a,m)=(b,m) (a,m)=(b,m)
定义: a , b a,b a,b是整数, m m m是正整数,形如 a x ≡ b ( m o d m ) ax≡b(mod\ m) ax≡b(mod m),且 x x x是未知整数的同余式称为一元线性同余方程.
定理: a , b a,b a,b是整数, m m m是正整数, ( a , m ) = d (a,m)=d (a,m)=d.如果 d ∣ b d|b d∣b,则方程恰有 d d d个模 m m m的不同余的解,否则方程无解。
证明:方程有解时, ( a x − b ) = y m (ax-b)=ym (ax−b)=ym, y y y为整数,即 a x − y m = b ax-ym=b ax−ym=b,由裴蜀定理可知,对任何整数 a 、 b a、b a、b和它们的最大公约数 d d d,关于未知数 x x x和 y y y的线性不定方程(称为裴蜀等式):若 a , b a,b a,b是整数,且 g c d ( a , b ) = d gcd(a,b)=d gcd(a,b)=d,那么对于任意的整数 x , y x,y x,y,都有 a x + b y ax+by ax+by一定是 d d d的倍数,特别地,一定存在整数 x , y x,y x,y,使 a x + b y = d ax+by=d ax+by=d成立。因为y为整数,不是定值,所以把上式化为 a d x − m d y = b d \frac{a}{d}x-\frac{m}{d}y=\frac{b}{d} dax−dmy=db,随着 y y y值变化, x x x存在 d d d个不同余的解。所以如果 ( a , m ) = d (a,m)=d (a,m)=d, d ∣ b d|b d∣b,那么方程恰有 d d d个不同余解 , d d d个解分别关于 m d \frac{m}{d} dm同余,分别为 x , x + m d , x + 2 ∗ m d , . . . , x + ( d − 1 ) ∗ m d x,x+\frac{m}{d},x+2*\frac{m}{d},...,x+(d-1)*\frac{m}{d} x,x+dm,x+2∗dm,...,x+(d−1)∗dm
求解一元线性同余方程时可以使用扩展欧几里得算法.
void exgcd(int a,int b,int&d,int&x,int&y)//扩展欧几里得算法
{
if(b==0)
{
x=1,y=0;
d=a;
return;
}
else
{
int r=exgcd(b,a%b,x,y); //r=GCD(a,b)=GCD(b, a%b)
int t=x;
x=y;
y=t-a/b*y ;
return;
}
}
int f(int a,int b,int m)//计算同余方程所有解
{
int x,y,d;
exgcd(a,m,d,x,y);
if(b%d)
return -1;//无解
x=x*(b/d)%m;
for(int i=1;i<=d;i++)
ans[i]=(x+(i-1)*m/d)%m;
}
任意的一元线性同余方程组都可以化为 x ≡ b ( m o d m ) x≡b(mod\ m) x≡b(mod m),而一元线性同余方程组就是多个这样的式子联合求解。
例如: x ≡ b 1 ( m o d m 1 ) x≡b_1(mod\ m_1) x≡b1(mod m1) 与 x ≡ b 2 ( m o d m 2 ) x≡b_2(mod\ m_2) x≡b2(mod m2),这两个方程就构成了一个同余方程组。
令 m = [ m 1 , m 2 ] m=[m_1,m_2] m=[m1,m2],此时方程组有解的充分必要条件是 ( m 1 , m 2 ) ∣ b 1 − b 2 (m_1,m_2)|b_1-b_2 (m1,m2)∣b1−b2,此时方程仅有一个非负整数解。
证明:讲两式写为 x = b 1 + m 1 y 1 , x = b 2 + m 2 y 2 x=b_1+m_1y_1,x=b_2+m_2y_2 x=b1+m1y1,x=b2+m2y2,联立可得 b 1 + m 1 y 1 = b 2 + m 2 y 2 b_1+m_1y_1=b_2+m_2y_2 b1+m1y1=b2+m2y2,即 m 1 y 1 − m 2 y 2 = b 1 − b 2 m_1y_1-m_2y_2=b_1-b_2 m1y1−m2y2=b1−b2,由裴蜀定理可知成立。此时方程的解即为 ( b 1 + m 1 y 1 ) % m (b_1+m_1y_1)\%m (b1+m1y1)%m或 ( b 2 + m 2 y 2 ) % m (b_2+m_2y_2)\%m (b2+m2y2)%m
上面式子 m 1 y 1 − m 2 y 2 = b 1 − b 2 m_1y_1-m_2y_2=b_1-b_2 m1y1−m2y2=b1−b2可由扩展欧几里得求解 y 1 y_1 y1和 y 2 y_2 y2.
对于多个方程的方程组,这样两两求解合并即可求出最后的解。
int solve()
{
int n,m1,b1,m2,b2,x,y,d,flag=1;
cin>>n>>m1>>b1;
for(int i=1;i<n;i++)
{
cin>>m2>>b2;
int c=b2-b1;
exgcd(m1,m2,d,x,y);
if(c%d!=0)
flag=0;
x=(x*c/d)%(m2/d);//求小于m2/d的解
b1=m1*x+b1;
m1=m1*(m2/d);//合并后m应为m1和m2的最小公倍数
}
if(flag) return b1;
else return -1;
}
中国剩余定理是中国古代求解一次同余式组的方法。是数论中一个重要定理。又称中国余数定理。
给定一个同余式组如下:
S { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) x ≡ a 1 ( m o d m 1 ) . . . x ≡ a n ( m o d m n ) S\left\{ \begin{aligned} &x≡a_1(mod\ m_1)&\\ &x≡a_2(mod\ m_2)&\\ &x≡a_1(mod\ m_1)&\\ &\ \ \ \ .&\\ &\ \ \ \ .&\\ &\ \ \ \ .&\\ &x≡a_n(mod\ m_n)&\\ \end{aligned} \right. S⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧x≡a1(mod m1)x≡a2(mod m2)x≡a1(mod m1) . . .x≡an(mod mn)
中国剩余定理说明:假设整数 m 1 , m 2 , . . . , m n m_1,m_2, ... ,m_n m1,m2,...,mn两两互质,则对任意的整数: a 1 , a 2 , . . . , a n a_1,a_2, ... ,a_n a1,a2,...,an,方程组 S S S有解,并且通解可以用如下方式构造得到:
设 M = ∏ i = 1 n m i , M i = M m i , t i = M i − 1 M=\prod\limits_{i=1}^n{m_i},M_i=\frac{M}{m_i},t_i=M_i^{-1} M=i=1∏nmi,Mi=miM,ti=Mi−1( t i t_i ti为 M i M_i Mi模 m i m_i mi意义下的逆元),即 t i M i ≡ 1 ( m o d m i ) t_iM_i≡1(mod\ m_i) tiMi≡1(mod mi)
那么方程组的通解 x = a 1 t 1 M 1 + a 2 t 2 M 2 + . . . + a n t n M n + k M x=a_1t_1M_1+a_2t_2M_2+...+a_nt_nM_n+kM x=a1t1M1+a2t2M2+...+antnMn+kM
在模M情况下只有一个解 x = ( ∑ i = 1 n a i t i M i ) m o d M x=(\sum\limits_{i=1}^n{a_it_iM_i})mod\ M x=(i=1∑naitiMi)mod M
下面证明摘自百度百科:
中国剩余定理求解同余方程组:
int m[maxx];
int intChina(int n)
{
int M=1,Mi,x0,y0,d,ans=0;
for(int i=1;i<=n;i++)
M*=m[i];
for(int i=1;i<=n;i++)
{
Mi=M/m[i];
exgcd(Mi,m[i],d,x0,y0)
ans=(ans+Mi*x0*a[i])%M;
}
return ans;
}
由中国剩余定理可得的两个定理
中国剩余定理应用:
poj1006.Biorhythms
题目大意:人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
#include
#include
using namespace std;
typedef long long ll;
const int maxx=1e6+7,M=21252;
void exgcd(int a,int b,int&d,int&x,int&y)
{
if(b==0)
{
x=1,y=0;
d=a;
return;
}
else
{
exgcd(b,a%b,d,x,y);
int t=x;
x=y;
y=t-a/b*y ;
return;
}
}
int m[maxx],a[maxx];
int intChina(int n)
{
int Mi,x0,y0,d,ans=0;
for(int i=1;i<=n;i++)
{
Mi=M/m[i];
exgcd(Mi,m[i],d,x0,y0);
ans=(ans+Mi*x0*a[i])%M;
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
int p,e,i,d,s=1;
m[1]=23,m[2]=28,m[3]=33;
while(cin>>p>>e>>i>>d&&p!=-1)
{
a[1]=p;
a[2]=e;
a[3]=i;
int ans=intChina(3);
while(ans<=d)
ans+=M;
cout<<"Case "<<s++<<": the next triple peak occurs in "<<ans-d<<" days."<<endl;
}
}