参考博客

Acdreamer


一次同余方程

a x b ( m o d <mtext>   </mtext> n )


分情况讨论
  1. 若有 ( a , n ) = 1 ,根据 欧几里得扩展,存在 l,m使得 a l + n m = 1 ,等式两边同时模n,得 a l 1 ( m o d <mtext>   </mtext> n ) ,对于
    a x b ( m o d <mtext>   </mtext> n )
    a l x b l ( m o d <mtext>   </mtext> n )
    x b l ( m o d <mtext>   </mtext> n )

  1. 若有 ( a , n ) = d , 对于
    a x b ( m o d <mtext>   </mtext> n )

移项

a x b 0 ( m o d <mtext>   </mtext> n )

n | ( a x b )

已知
d | a , d | n

于是
d | b

所以同余方程有解的条件是 d | b
a 1 = a / d , b 1 = b / d , n 1 = n / d
则有
n 1 | ( a 1 x b 1 )

即为
a 1 x b 1 ( m o d <mtext>   </mtext> n 1 ) <mtext>   </mtext> <mtext>   </mtext> <mtext>   </mtext> <mtext>   </mtext> <mtext>   </mtext> ( a 1 , n 1 ) = 1

就变成情况1,可以解出此时的
x b 1 l ( m o d <mtext>   </mtext> n 1 )

x = b 1 l + n 1 t
t的取值范围 为(0,d-1)

中国剩余定理

解线性同余方程,运用拉格朗日插值法,得孙子定理

模板

int m[maxn];
int  China(int a[],int n,int b[])//其中a[]是模数,b[] 是余数
{
    int M = 1;
    for(int i = 0;i < n;++i)
        M *= a[i];
    int ans = 0;
    for(int i = 0;i < n;++i)
    {
        int Mi = M/a[i];
        LL x,y;
        ex_gcd(Mi,a[i],x,y);
        ans += b[i] * x*Mi;
    }
    ans = (ans%M + M) %M;
    return ans;
}

扩展

合并两个模数
假设
          y = a 1 ( m o d <mtext>   </mtext> m 1 )
         y = a 2 ( m o d <mtext>   </mtext> m 2 )

         x a 1 + t 1 m 1 ; 1
         x a 2 + t 2 m 2 ; 2
两式相减得         t 1 m 1 t 2 m 2 = a 1 a 2 3
        利用欧几里得扩展求出 t 1 带入(1) 求出一个特解 x

y = x ( m o d <mtext>   </mtext> l c m ( m 1 , m 2 ) )

证明 x与y同余于 l c m m 1 , m 2 )
m 1 | x y
m 2 | x y
所以 l c m ( m 1 , m 2 ) | x y ,所以x和y关于 l c m ( m 1 , m 2 ) 同余