基础数论

基础数论


整除

一、概念

若整数a除以非零整数b,商为整数,且余数为零,我们就说b能整除a,即b|a,读作"b整除a"或"a除以b"。
可以理解为b是a的因子,a是b的倍数。

二、性质

\(1.传递性:如果a\:|\:b且b\:|\:c,那么a\:|\:c\)

\(2.结合性:a\:|\:b且a\:|\:c,那么对于任意整数x和y,有a\:|\:(b*x+c*y)\)

\(3.同除性:设m\:!= 0,那么a\:|\:b等价于(m*a)\:|\:(m*b)\)

\(4.条件性: a = q*b + r\:, b\:|\: a等价于 r\:|\:b\)

\(5.a\:|\:c\:,\: b\:|\:c\:,\: gcd(a,b)=1 那么 ab\:|\:c\)

\(6.p\:|\:ab , 那么p\:|\:a或p\:|\:b , 如果gcd(p,a) = 1 , 那么p\:|\:b\)


同余

一、概念

\(给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即m|(a-b),那么就称整数a与b对模m同余。\)
\(记作a≡b(mod\:m)。对模m同余是整数的一个等价关系。可表示为a≡b(mod\:m)⇐⇒m|(a−b)\)

二、性质

\(1.可加减性:a\equiv b(mod\:m) \ , \ c\equiv d(mod\:m) \ \rightarrow a+c\equiv b+d(mod\:m)\)
\(证明:可知有:m\:|\:a-b \ , \ m\:|\:c-d \ , \ 根据整除结合性有m\:|\:a+c-b-d \ , \ 得证 a+c\equiv b+d(mod\:m)\)

\(2.可乘性:a\equiv b(mod\:m) \ , \ c \equiv d (mod\:m) \ \rightarrow \ ac \equiv bd(mod\:m)\)
\(证明:可知有:a = q_1m+b , c = q_2m+d \ \rightarrow \ ac = (q_1q_2m+q_1d+q_2b)m + cd 。根据同余得证 \rightarrow ac\equiv bd(mod\:m)\)

\(3.注意除法不具有一般消去律:gcd(c , m) = d \ , \ ac \equiv bc(mod\:m) \rightarrow a \equiv b (mod\:\frac{m}{d})\)
\(证明:已知有m\:|\:c(a-b)。 两边同时除d \ , \ \frac{m}{d} \:|\: \frac{c}{d} (a-b) , 可知gcd(\frac{c}{d} , \frac{m}{d}) = 1 , 根据上整除性质5可得, \frac{m}{d} | (a - b) , 得证 a \equiv b (mod\:\frac{m}{d})\)


模运算与取余

一、概念

取模运算(“Modulus Operation”)和取余运算(“Remainder Operation ”)两个概念有重叠的部分但又不完全一致。
主要的区别在于对负整数进行除法运算时操作不同。取模主要是用于计算机术语中。取余则更多是数学概念。 ---百度百科

二、区别及运算

\(0<=a \: mod \: m <= m\:,\:-m<=a \% b<=m , 所以在求余时,模为负数要转为正数,方法:(a\%m+m)\%m\)
计算机上有几种对于结果取整的方法:
1.向上取整:向+∞方向取最接近精确值的整数,也就是取比实际结果稍大的最小整数,也叫 Ceiling 取整。
2.向-∞方向取最接近精确值的整数,也就是取比实际结果稍小的最大整数,也叫 Floor 取整。
3.向零取整,向0方向取最接近精确值的整数,换言之就是舍去小数部分,因此又称截断取整(Truncate)。
c\java:对于模运算采用向零取整。(a % b = a - (a/b)*b)
-17 % 10 的计算结果如下:r = (-17) - (-17 / 10) x 10 = (-17) - (-1 x 10) = -7
17 % -10 的计算结果如下:r = 17 - (17 / -10) x (-10) = (17) - (-1 x -10) = 7
-17 % -10 的计算结果如下:r = (-17) - (-17 / -10) x (-10) = (-17) - (1 x -10) = -7


欧几里得

一、gcd与lcm概念

最大公约数:指两个或多个整数共有约数中最大的一个。\(a,b的最大公约数记为gcd(a,b)\).
最小公倍数:两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。\(a,b的最大公倍数记作lcm(a,b)\).

二、gcd与lcm性质

\(1.gcd(a,b) = gcd(b,a)\)
\(2.gcd(a,b) = gcd(a-b,b)(a>=b)(证明:假设公约数为d , d\:|\:a , d\:|\:b , 根据整除性质的结合性\rightarrow d\:|\:(a-b) , d\:|\:b)\)
\(3.gcd(a,b) = gcd(a\% b , b)(证明:假设a \:,b的gcd(a,b) = d \:,\: d\:|\:a \:,\: d\:|\:b \:,\: a = d*q+r \: \rightarrow \: d\:|\:r . 得证gcd(a,b) = gcd(r,b) = gcd(a\%b , b))\)
\(4.lcm(a,b) = \frac{a*b}{gcd(a,b)}(a*b必为在a,b的倍数,除去最大共因子即为最小公倍数)\)

三、从唯一分解定理看gcd(a,b)、lcm(a,b)和a*b间的关系

由唯一分解定理:

\[a = p^{e_1}_{1} * p^{e_2}_{2} * p^{e_3}_{3} * ... * p^{e_n}_{n} \]

\[b = p^{f_1}_{1} * p^{f_2}_{2} * p^{f_3}_{3} * ... * p^{f_n}_{n} \]

\[gcd(a,b) = \Pi^{n}_{i=1}p^{min(e_i , f_i)}_{i} \]

\[lcm(a,b) = \Pi^{n}_{i=1}p^{max(e_i , f_i)}_{i} \]

\[a * b = \Pi^{n}_{i=1} p_i^{min(e_i,f_i)+max(e_i ,f_i)} \]

三、欧几里得求gcd

\(已知:gcd(a , b) = gcd(a\%b , b) = gcd(b , a\%b)\)
\(将b看作新的a即a',a\%b看作b',重复以上两步。直到gcd(a'' , 0) = a''结束.\)

int gcd(int a , int b){
    if(b == 0){
        return a ;
    }else{
        gcd(b , a%b);
    }
    //return b==0?a:gcd(b,a%b);
}

扩展欧几里得

一、简介

\(解二元一次不定方程a*x+b*y=gcd(a,b).求一组解(x_0,y_0)\)

\[a*x_1 + b*y_1 = gcd(a,b) \]

\[b*x_2 + (a\%b)*y_2 = gcd(b , a\%b) \]

由欧几里得可知上面两式相等.

\[a*x_1 + b*y_1 = b*x_2 + (a-[\frac{a}{b}]*b)*y_2 \]

对等号右边进行合并同类项得

\[a*x_1 + b*y_1 = a*y_2 + b*(x_2-[\frac{a}{b}]*y_2) \]

得到递推式:

\[x_1 = y_2 \]

\[y1 = x_2 - \frac{a}{b} * y_2 \]

\(终止条件:当b = 0 时,有 x_2 = 1 , y_2 = 0.根据递推式反推x_0,y_0.\)
代码实现:\(可以知道求x_0 , y_0过程是一个递归过程,需要先求得x_2,y_2再根据递推式倒推。\)

void ex_gcd(int a , int b , int &d , int &x , int &y){
    if(!b){//终止条件b=0
        d = a ;
        x = 1 ;
        y = 0 ;
    }else{
        ex_gcd(b , a%b , d , x , y);//递归
        //倒推过程
        int t = x ;
        x = y ;
        y = t - (a/b)*y;
    }
}

int cal(int a , int b , int c){
    ex_gcd(a , b , d , x , y);
    int t = b/d;
    return (x%t+t)%t;//得到x得最小正整数解
}

可以知道二元一次方程具有多组解:

\[x = x_0 + \frac{b}{d}*k (k\in Z) \]

\[y = y_0 + \frac{a}{d}*k (k\in Z) \]

一般解题都是要求最小正整数解:\(x = (x\%\frac{b}{d}+\frac{b}{d})\%\frac{b}{d}\),将x代入方程求出y

二、解二元一次不定方程ax+by=c

有解条件\(gcd(a,b)|c\).

\[x = x*\frac{c}{gcd(a,b)} + \frac{b}{d}*k \]

\[y = y*\frac{c}{gcd(a,b)} + \frac{a}{d}*k \]


逆元

一.概念

逆元素是指一个可以取消另一给定元素运算的元素,在数学里,逆元素广义化了加法中的加法逆元和乘法中的倒数。---百度百科

在数论同余方程中,对于\(a * x≡b(mod\:m)\)这个方程如果我们要求解的话其实是比较复杂的,可是如果我们可以求出\(a * y≡1(mod\:m)\)中的y的话,
在上面那个方程上同乘以y就可以得到,\(x=b * y(mod\:m)\),是不是很神奇,我们也称y是a在mod m的条件下的逆元,写作\(x^{-1}\)

二.费马小定理求逆元

费马小定理(Fermat's little theorem)是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p) ---百度百科

将费马小定理等式两边同除a(即乘以\(a^{-1}\)) , 得\(a^{-1} \equiv a^{p-2}(mod p)\) , 所以a的逆元就等于a在模p下得p-2次方,快速幂求解。
注意:费马小定理的两个条件:\(gcd(a,p)=1、p为质数\)

int quickpow(int a , int b , int mod){
    int ans = 1 ;
    while(b){
        if(b&1){
            ans = ans * a % mod ;
        }
        b >>= 1 ;
        a = a * a % mod ;
    }
    return ans ;
}

int inv(int a , int m){//a在模m下的逆元
    return quickpow(a , m-2 , m);
}

三、扩展欧几里得求逆元

费马小定理求逆元代码很简洁,但有时候求逆元模数p可能不是质数,但有\(gcd(a,p) = 1\),存在逆元。
这时候扩展欧几里得得排上用场了。
\(a*x \equiv 1 (mod\:p)\),可以转化成二元一次不等式,\(a*x+p*k = 1\),这时求出x的最小正整数解\(x_0\)即为a在模p下得逆元。

void ex_gcd(int a , int b , int &d , int &x , int &y){
    if(!b){
        d = a ;
        x = 1 ;
        y = 0 ;
    }else{
        ex_gcd(b , a%b , d , x , y);
        int t = x ;
        x = y ;
        y = t - (a/b)*y;
    }
}

int inv(int a , int p , int c){
    ex_gcd(a , p , d , x , y);
    if(gcd(a,p) != 1) return 0;//不存在逆元
    int t = b/d;
    return (x%t+t)%t;//x得最小正整数解
}

四、线性筛逆元

首先有\(1^{-1} \equiv 1(mod p)\)
\(p = k * i + r(k是\frac{p}{i}得商 , r是余数)\)

\[k*i+r \equiv 0(mod p) \]

两边乘以\(i^{-1} , r^{-1}\),得

\[k * r^{-1} + i^{-1} \equiv 0 (mod p) \]

移项得

\[i^{-1} \equiv -k*r^{-1} (mod p) \]

将k和r带入得

\[i^{-1} \equiv -[\frac{p}{i}]*(p\%i)^{-1}(mod p) \]

所以有递推式

\[inv[i] = (p - [\frac{p}{i}]) * inv[p\%i] \% p \]

void solve(){
    inv[1] = 1 ;
    for(int i = 2 ; i < p ; i++){
        inv[i] = (p - p/i) * inv[p%i] % p ;
    }
}

五、阶乘逆元

阶乘逆元\(inv[i+1] = \frac{1}{(i+1)!}\)有递推关系:\(inv[i] = inv[i+1] * (i+1)\)
阶乘逆元一般会在求组合数且结果需要mod时出现,先求出1-n的阶乘,再利用扩展欧几里得或则费马小定理求出n阶乘的逆元,根据递推关系倒退1-n-1阶乘得逆元

inv[N]=quickpow(fac[N],mod-2);
for(ll i=N-1;i>=0;i--)
    inv[i]=(inv[i+1]*(i+1))%mod;

中国剩余定理

一、介绍

中国剩余定理是求解一元线性同余方程组

\[ \left\{ \begin{aligned} x \equiv a_1(mod\:m_1)\\ x \equiv a_2(mod\:m_2)\\ ................\\ x \equiv a_n(mod\:m_n) \end{aligned} \right.\]

\(m_1 , m_2 , ... , m_n\)两两互质,则对任意整数\(a_1,a_2,...,a_n\),求最小非负整数解x。

二、求解

\(M = \Pi^{n}_{i=1}m_i\),M为所有模数得最小公倍数。
\(t_i 为同余方程\frac{M}{m}*t_i \equiv 1(mod\:m_i)\)的最小非负整数解
则有一个解为 \(x = \Sigma^{n}_{i=1}a_i*\frac{M}{m_i}*t_i\)
同解为\(x = x + M*q\)
最小非负整数解\((x\%M+M)\%M.\)

int ex_gcd(int a , int b , int &x , int &y){
    if(!b){
        x = 1 ;
        y = 0 ;
        return a ;
    }
    d = ex_gcd(b , a%b , x , y);
    int t = x;
    x = y ;
    y = t - a/b*y;
    return d ;
}

int CTM(){
    int M = 1 , ans = 0 ;
    rep(i , 1 , n){
        M *= m[i];
    }
    rep(i , 1 , n){
        int t = M/m[i];
        d = ex_gcd(t , m[i] , x , y);
        x = (x % (m[i]/d) + (m[i]/d)) % (m[i]/d) ;//求得x得最小正整数解
        ans = (ans + a[i]*t*x)%M;//求和
    }
    return ans ;
}

三、解扩展中国剩余定理

同样是解一元线性同余方程组,只是不满足\(m_1 , m_2 , ... , m_n\)两两互质。
解法思想是两两方程合并。
现在演示合并前两个同余方程

\[x \equiv a_1(mod\:m_1) \]

\[x \equiv a_2(mod\:m_2) \]

转为线性方程有

\[x + m_1*u = a_1(u为任意整数) \]

\[x - m_2*v = a_2(v为任意整数) \]

1式减2式得

\[m_1*u + m_2*v = a_1 - a_2 \]

有解条件为\(gcd(m_1, m_2)|a_i - a_2\)
通过扩展欧几里得可以得到一组解\((u_0 , v_0)\)
有通解\(u = u_0 + \frac{m_2}{gcd(m1,m2)}*k\)(k为任意整数)
带入1式得

\[x + lcm(m_1 , m_2)*k = a_1 - m_1*u_0 \]

有合并后同余方程

\[x \equiv a_1 - m_1*u_0(mod\:lcm(m_1 , m_2)) \]

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

int EX_CRT(){
    for(int i = 2 ; i <= n ; i++){
        int d = ex_gcd(m[1] , m[i] , x , y);
        if((a[1] - a[i])%d){
            return -1 ;
        }
        int mo = m[i]/d;
        x = ((x * (a[1]-a[i])/d)%mo+mo)%mo ;
        int lcm = m[1] / __gcd(m[1] , m[i])  * m[i];
        a[1] = ((a[1]%lcm - m[1]%lcm * x % lcm ) % lcm + lcm) % lcm ; 
        m[1] = lcm;
    }
    return a[1];
}

素数筛

移步另一篇文章素数筛

posted @ 2020-04-20 19:59  无名菜鸟1  阅读(483)  评论(0编辑  收藏  举报