同余问题及线性同余方程(组)

    科技2024-10-04  30

    同余

    定义

    如果a,b除以c的余数相同,就说a和b关于模c同余记作a≡b(mod c)

    还可以这样理解 a − b = t a-b=t ab=t,若 t ∣ c t|c tc(表示t可以被c整除),则 a ≡ b ( m o d c ) a≡b(mod c) ab(modc)

    性质

    同余关系是一种等价关系。

    1.自反性:一个数永远和自己本身同余 a≡a(mod)

    2.对称性:a和b同余,b也就同余a,即 a≡b(mod m)等价于b≡a(mod m)

    3.传递性:a和b同余,b和c也同余,可以推出a和c也是同余的

    运算

    加减法

    若 a≡b(mod m),x≡y(mod m)则有,a+x≡b+y(mod m) 证明: 根据定义,若 a≡b(mod m)则可以总可找到k1,k2满足 :a+k1*m=b+k2*m 同理,对于x≡y(mod m),也总可找到k3,k4满足:x+k3*m+y+k4*m 等式两边分别相加有

    ( a + x ) + m ∗ ( k 1 + k 3 ) = ( b + y ) + m ∗ ( k 2 + k 4 ) (a+x)+m*(k1+k3)=(b+y)+m*(k2+k4) (a+x)+m(k1+k3)=(b+y)+m(k2+k4) 两边同时取模m即得到 a+x≡b+y(mod m)

    乘法

    若 a≡b(mod m),x≡y(mod m)则有,ax≡by(mod m) 证明与加法相似(略)

    一个特殊的?除法?

    如果ac≡bc(mod m),且c和m互质,则有a≡b(mod m)(就是说同余式两边可 以同时除以一个和模数互质的数)。 证明: 对于ac≡bc(mod m),我们总可以找到k1,k2使得 a c + k 1 ∗ m = b c + k 2 ∗ m ac+k1*m = bc+k2*m ac+k1m=bc+k2m 移项有 c ∗ ( a − b ) = m ∗ ( k 2 − k 1 ) c*(a-b)=m*(k2-k1) c(ab)=m(k2k1) c ∗ ( a − b ) / m = ( k 2 − k 1 ) c*(a-b)/m=(k2-k1) c(ab)/m=(k2k1) 所以,可知, c ∗ ( a − b ) ∣ m c*(a-b)|m c(ab)m 又因为c与m是互质(互素)的,因此, ( a − b ) ∣ m (a-b)|m (ab)m 所以得到 a ≡ b ( m o d   m ) a \equiv b(mod\, m) ab(modm)

    线性同余方程

    给出a,b,m,求一整数x满足 a*x≡b(mod m) ,或给出无解 因为未知数的次数为1,所以我们称之为线性同余方程。 根据同余的定义,该式子等价于 a ∗ x % m = b a*x\%m=b ax%m=b 也就是说, a ∗ x − b a*x-b axb是m的倍数 那么不妨设 a x − b = − m y ax-b=-my axb=my ax+my=b 根据裴蜀定理及扩欧定理(exgcd)求解可得到任一特解 设特解为 x 0 x_{0} x0,则其通解可以表示为 { x 0 + k m d ∣ k ∈ Z } \lbrace x_{0}+ k\cfrac{m}{d}\mid k\in Z \rbrace {x0+kdmkZ}其中 d = g c d ( a , m ) d=gcd(a,m) d=gcd(a,m)

    推论:其最小正整数可表示为 ( x 0 % ( m d ) + m d ) % ( m d ) (x_0\%(\frac{m}{d})+\frac{m}{d})\%(\frac{m}{d}) (x0%(dm)+dm)%(dm)

    裴蜀(贝祖Bezout)定理

    定理: 对于给定的正整数a,b方程ax+by=c有解的充要条件为: c=k*gcd(a,b),k∈Z(c | gcd(a,b))

    证明:

    https://blog.csdn.net/a_forever_dream/article/details/83859354

    推论:

    a,b 互质的冲要条件是,ax+by=1 整数解对于n元不定方程: a 1 x 1 + a 2 x 2 + a 3 x 3 + … … + a n x n = m a_{1}x_{1}+a_{2}x_{2}+a_{3}x_{3}+……+a_{n}x_{n}=m a1x1+a2x2+a3x3++anxn=m当且仅当 g c d ( a 1 , a 2 , a 3 , a 4 , … … , a n ) ∣ m gcd(a_{1},a_{2},a_{3},a_{4},……,a_{n}) |m gcd(a1,a2,a3,a4,an)m时有整数解 a 1 , a 2 , a 3 , a 4 , … … , a n a_{1},a_{2},a_{3},a_{4},……,a_{n} a1,a2,a3,a4,an互质的充要条件是 方程 a 1 x 1 + a 2 x 2 + a 3 x 3 + … … + a n x n = m a_{1}x_{1}+a_{2}x_{2}+a_{3}x_{3}+……+a_{n}x_{n}=m a1x1+a2x2+a3x3++anxn=m有整数解

    扩欧定理

    扩欧定理可以求解形如 a x + b y = c ax+by=c ax+by=c,( c ∣ g c d ( a , b ) c|gcd(a,b) cgcd(a,b)),其求解过程就是不断递归的求解gcd(a,b)同时操作两个未知量x和y的值,当求解出gcd(a,b)时,即可回溯推出x,y,这里求出的x,y是一组特解。

    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; } 注意到: 实际求解的x,y实际上是方程$ax+by=gcd(a,b)$的解,因此在必要时要乘$c/gcd(a,b)$获得符合条件的解 在函数参数部分,x和y使用传址是为了直接对传入的变量进行操作。 根据前面的同余部分知识,我们可以最小正整数化x和y 即

    [ x % c g c d ( a , b ) + c g c d ( a , b ) ] % c g c d ( a , b ) [x\%\frac{c}{gcd(a,b)}+\frac{c}{gcd(a,b)}]\%\frac{c}{gcd(a,b)} [x%gcd(a,b)c+gcd(a,b)c]%gcd(a,b)c [ y % c g c d ( a , b ) + c g c d ( a , b ) ] % c g c d ( a , b ) [y\%\frac{c}{gcd(a,b)}+\frac{c}{gcd(a,b)}]\%\frac{c}{gcd(a,b)} [y%gcd(a,b)c+gcd(a,b)c]%gcd(a,b)c 这种最小正整数化的思想也可以用在其他取模操作上可以避免在取模的过程中出现负数等情况。

    线性同余方程组

    顾名思义我们这次要求解一组线性同余方程

    x ≡ b 1 ( m o d   m 1 ) x≡b_1(mod\,m_1) xb1(modm1) x ≡ b 2 ( m o d   m 2 ) x≡b_2(mod\,m_2) xb2(modm2) x ≡ b 3 ( m o d   m 3 ) x≡b_3(mod\,m_3) xb3(modm3) x ≡ b 4 ( m o d   m 4 ) x≡b_4(mod\,m_4) xb4(modm4) …… x ≡ b n ( m o d   m n ) x≡b_n(mod\,m_n) xbn(modmn)

    这种方程有两种常见的样式 ① m 1 , m 2 , m 3 … … m n m_1,m_2,m_3……m_n m1,m2,m3mn是两两互质 ② m 1 , m 2 , m 3 … … m n m_1,m_2,m_3……m_n m1,m2,m3mn不一定满足互质

    中国剩余定理求解(CRT)

    对于①可以用中国剩余定理求解

    在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:

    找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加15∗2+21∗3+70∗2得到和233。用233除以3,5,7三个数的最小公倍数105,得到余数23,即233%105=23。这个余数23就是符合条件的最小数

    用数学语言来说,这个问题解法的本质是从5和7的公倍数中找一个除以3余2的数 n 1 n_{1} n1,从3和7的公倍数中找一个除以5余3的数 n 2 n_{2} n2,从3和5的公倍数中找一个除以7余2的数 n 3 n_{3} n3,再将三个数相加得到解。在求 n 1 n_{1} n1 n 2 n_{2} n2 n 3 n_{3} n3时又用了一个小技巧,以 n 1 n_{1} n1为例,并非从5和7的公倍数中直接找一个除以3余2的数,而是先找一个除以3余1的数,再乘以2。也就是先求出5和7的公倍数模3下的逆元,再用逆元去乘余数。 最后,我们还要清楚一点,n1+n2+n3只是问题的一个解,并不是最小的解。如何得到最小解?我们只需要从中最大限度的减掉掉3,5,7的公倍数105即可。 于是中国剩余定理的公式就出来了 设有正整数 m 1 , m 2 , m 3 … … m n m_1,m_2,m_3 ……m_n m1,m2,m3mn两两互质,则方程组 x ≡ b 1 ( m o d   m 1 ) x≡b_1(mod\,m_1) xb1(modm1) x ≡ b 2 ( m o d   m 2 ) x≡b_2(mod\,m_2) xb2(modm2) x ≡ b 3 ( m o d   m 3 ) x≡b_3(mod\,m_3) xb3(modm3) x ≡ b 4 ( m o d   m 4 ) x≡b_4(mod\,m_4) xb4(modm4) 有整数解,并且在模 M = m 1 ∗ m 2 ∗ m 3 ∗ … … ∗ m n M=m_1*m_2*m_3*……*m_n M=m1m2m3mn下解是唯一的。 其解为 x ≡ ( b 1 ∗ M 1 ∗ M 1 − 1 + b 2 ∗ M 2 ∗ M 2 − 1 + b 3 ∗ M 3 ∗ M 3 − 1 + … … + b n ∗ M n ∗ M n − 1 ) m o d   M x≡(b_1*M_1*M_1^{-1}+b_2*M_2*M_2^{-1}+b_3*M_3*M_3^{-1}+……+b_n*M_n*M_n^{-1})mod\, M x(b1M1M11+b2M2M21+b3M3M31++bnMnMn1)modM 其中 M i = M / m i M_i=M/m_i Mi=M/mi, M i − 1 是 M i 取 模 m i 的 逆 元 M_i^{-1}是M_i取模m_i的逆元 Mi1Mimi 补充两个求逆元的常用方法

    费马小定理求逆元

    费马小定理描述如下 a p − 1 ≡ 1 ( m o d   p ) a^{p-1}≡1(mod\, p) ap11(modp)当且仅当p为质数(素数)的时候成立 所以有推论: a ∗ a p − 2 ≡ 1 ( m o d   p ) a*a^{p-2}≡1(mod\,p) aap21(modp) 所以 a − 1 = a p − 2 a^{-1}=a^{p-2} a1=ap2,用快速幂可解

    扩欧定理求逆元

    a − 1 = x a^{-1}=x a1=x,则有 a ∗ x ≡ 1 ( m o d   p ) a*x≡1(mod\, p) ax1(modp) 根据同余的定义,可转化为下式: a ∗ x + p ∗ y = 1 a*x+p*y=1 ax+py=1 直接带入exgcd算法即可求解 注意:这里实际求解的是二元方程① a ∗ x + p ∗ y = g c d ( a , p ) a*x+p*y=gcd(a,p) ax+py=gcd(a,p)①所对应的解X。因此 a ∗ x + p ∗ y = 1 a*x+p*y=1 ax+py=1中的x应该为 X / g c d ( a , p ) X/gcd(a,p) X/gcd(a,p)

    LL CRT(LL b[], LL m[], int n)//b是余数,m是模 { LL M = 0, tx, ty, x = 0; for (int i = 1; i <= n; ++i) { M *= m[i]; } for (int i = 1; i <= n; ++i) { LL Mi = M / m[i]; LL t = exgcd(Mi, m[i], tx, ty); x = (x + Mi*b[i] / t * x) % M; } return x; }

    扩展中国剩余定理(EX_CRT)

    对于②需要合并方程然后用扩欧定理求解 因为不满足互素的条件,所以中国剩余定理在这里并不适用。因此我们需要合并方程来减少方程数量并适用扩欧定理求解。 我们先拿出前两个方程 x ≡ b 1 ( m o d   m 1 ) x≡b_1(mod\,m_1) xb1(modm1) x ≡ b 2 ( m o d   m 2 ) x≡b_2(mod\,m_2) xb2(modm2) 根据定义,我们可以将两式分别转化为如下形式 x = b 1 + k 1 ∗ m 1 x=b_1+k_1*m_1 x=b1+k1m1 x = b 2 + k 2 ∗ m 2 x=b_2+k_2*m_2 x=b2+k2m2 联立两式移项 k 1 ∗ m 1 − ( b 2 − b 1 ) = k 2 ∗ m 2 k_1*m_1-(b_2-b_1)=k_2*m_2 k1m1(b2b1)=k2m2 d = g c d ( m 1 , m 2 ) d=gcd(m1,m2) d=gcd(m1,m2)两边同时除d 得到 k 1 ∗ m 1 d − b 2 − b 1 d = k 2 ∗ m 2 d \frac{k_1*m_1}{d}-\frac{b_2-b_1}{d}=\frac{k_2*m_2}{d} dk1m1db2b1=dk2m2 两边同时取模 k 2 ∗ m 2 k_2*m_2 k2m2 得到 k 1 ≡ b 2 − b 1 m 1 ( m o d   m 2 d ) k_1≡\frac{b_2-b_1}{m1}(mod\,\frac{m_2}{d}) k1m1b2b1(moddm2) 则必然存在一最小 T T T满足 T ≡ b 2 − b 1 m 1 ( m o d   m 2 d ) T≡\frac{b_2-b_1}{m1}(mod\,\frac{m_2}{d}) Tm1b2b1(moddm2)使得 k 1 ≡ T ( m o d   m 2 d ) k_1≡T(mod\,\frac{m_2}{d}) k1T(moddm2) 带入 x = b 1 + k 1 ∗ m 1 x=b_1+k_1*m_1 x=b1+k1m1得到 x = b 1 + m 1 ∗ ( T + m 2 d ∗ C ) x=b_1+m_1*(T+\frac{m_2}{d}*C) x=b1+m1(T+dm2C)(C是任意整数) x = b 1 + m 1 ∗ T + m 2 ∗ m 1 d ∗ C x=b_1+m_1*T+\frac{m_2*m_1}{d}*C x=b1+m1T+dm2m1C

    x ≡ ( b 1 + m 1 ∗ T ) ( m o d   m 2 ∗ m 1 d ) x≡(b_1+m_1*T)(mod\,\frac{m_2*m_1}{d}) x(b1+m1T)(moddm2m1) ① 由 k 1 ∗ m 1 − k 2 ∗ m 2 = ( b 2 − b 1 ) k_1*m_1-k_2*m_2=(b_2-b_1) k1m1k2m2=(b2b1)可由扩欧定理解出k1 注:这里实际计算的是 k 1 ∗ m 1 − k 2 ∗ m 2 = g c d ( k 1 , k 2 ) k_1*m_1-k_2*m_2=gcd(k1,k2) k1m1k2m2=gcd(k1,k2),因此在使用 k 1 k_1 k1时需要乘上 ( b 2 − b 1 ) / g c d ( b 1 , b 2 ) (b_2-b_1)/gcd(b_1,b_2) (b2b1)/gcd(b1,b2) 根据刚刚算出的 k 1 ≡ T ( m o d   m 2 d ) k_1≡T(mod\,\frac{m_2}{d}) k1T(moddm2)由于同余的等价性,有 T ≡ k 1 ( m o d   m 2 d ) T≡k_1(mod\,\frac{m_2}{d}) Tk1(moddm2) 则可最小化 T = ( k 1 % m 2 d + m 2 d ) % m 2 d T=(k_1\%\frac{m_2}{d}+\frac{m_2}{d})\%\frac{m_2}{d} T=(k1%dm2+dm2)%dm2

    对比①式有 b 1 = b 1 + m 1 ∗ T b_1=b_1+m_1*T b1=b1+m1T m 1 = m 1 ∗ m 2 d m_1=\frac{m_1*m_2}{d} m1=dm1m2(实际运算的时候先乘后除较优) 这样操作一遍,我们合并了 x ≡ b 1 ( m o d   m 1 ) x≡b_1(mod\,m_1) xb1(modm1) x ≡ b 2 ( m o d   m 2 ) x≡b_2(mod\,m_2) xb2(modm2)两个式子 这样依次迭代下去,最后得到的b1就是方程组的最小非负数解

    代码 若输入的数据有无解的情况,返回-1,否则返回最小正整数解

    //x=b1(mod m1) LL ex_CRT(LL b[], LL m[], int n)//从1~n { LL m1, m2, b1, b2, x0, y0, aa, bb, c, d; b1 = b[1], m1 = m[1]; bool fl = 1; for (int i = 2; i <= n; ++i) { m2 = m[i], b2 = b[i]; aa = m1; bb = m2; c = b2 - b1; d = exgcd(aa, bb, x0, y0); if (c % d) { fl = 0; break; } LL t = bb / d; x0 = (x0 * (c / d) % t + t) % t; b1 = b1 + m1 * x0; m1 = m1 / d * m2; } if (fl) { return b1; } else { return -1; } }

    求线性同余方程组小于N的解的个数

    这个问题与同余方程组的通解有关。

    我们通过CRT及EX_CRT两个算法求出来的一般都是最小非负整数解(不是的话也得化成最非负整数解),设该解为 x 0 x_0 x0,不论是那种算法, x 0 x_0 x0一定是由模 L C M ( m 1 , m 2 , … … m n ) LCM(m_1,m_2,……m_n) LCM(m1,m2,mn)得到的。(加LCM是为了包含EX_CRT中模数不满足两两互素的情况,其实与CRT算法中的M是同一意义。)

    根据同余的定义,所有的正整数解可以表示为 x = x 0 + k ∗ l c m x={x_0+k*lcm} x=x0+klcm,(设 l c m = L C M ( m 1 , m 2 , … … m n ) lcm=LCM(m_1,m_2,……m_n) lcm=LCM(m1,m2,mn)) 那么小于n的解的个数一定是 a n s = 1 + ( n − x 0 ) / l c m ans=1+(n-x_0)/lcm ans=1+(nx0)/lcm,其实就是在求有多少个k满足 x < n x<n x<n,最后把本身加上。在这里要特别注意题目要求,有的题目要求非负数,有的题目要求正整数。这就要特判一下 x 0 = 0 x_0=0 x0=0的情况。

    Processed: 0.032, SQL: 8