数论知识

先言

本篇文章部分内容进行了相互穿插,请结合目录食用 。 如有不便,望见谅。

模运算

顾名思义 , 在模意义下进行运算,满足普通加法减法乘法运算 。
例如 \(a + b = c (mod \ \ p) => a\ \ mod \ \ p + b \ \ mod = c (mod \ \ p)\) 拿一个具体数字 , 即为
\(5 + 7 = 5 (mod \ \ 7) => 5 \ \mod \ \ 7 + 7 \ \ mod \ \ 7 = 5 + 0 = 5 (mod \ \ 7)\)
减法同样如此,但是在减法进行计算的时候,有可能会变成负数,但我们尽量不想让其变成负数,那我们可以转化成这样 $ ( (a - b )mod \ \ c + c )mod \ \ c$ 与 \((a - b) mod \ \ c\) 在模意义下是满足相等的。

除法则是满足不满足的,只有当 \(p\) 为质数时, 才可以进行 。

快速幂

幂运算就是 \(a^b\) 这样的运算 。快速幂就是将 \(a^b\) 转化成 \((a ^{\frac{b}{2}} )^2\) ,从而达到快速计算,同时对 \(b\) 进行一下讨论是否为奇数。
\(Code\) 模板

int quick_pow(int a , int b , int p) //a ^ b % p
{
	int ret = 1 ; 
	while(b) 
	{
		if(b & 1) ret = ret * a % p ; //指数为奇数 。
		a = a * a % p ; 
		b >>= 1 ;
	}
	return ret ; 
}

模板题 \(Code\)
略微推一下出来的模板题 \(Code\)

素数(质数)

定义就是只能够被 \(1\) 或者他自身整除的数字 。

判定

\(1.\)判断一下 $2 \to n - 1 $ 是否能为 \(n\) 的因子 ,复杂度 \(O(n)\)

n 一定能够被分解成\(a \times b\) 我们假设 \(a < b\) 那么我们只需要枚举 \(a\) 即可,因为如果 \(a\) 不满足乘除 \(n\) ,那么也不会有其它数能乘除 \(n\) ,同时 可以显然 \(a\) 的上界为 \(\sqrt n\)

\(2.\) 判断一下 \(2 \to \sqrt n\) ,看一下能否为 \(n\) 的因子,复杂度 \(O(\sqrt n)\)

筛法

算术基本定理
\(x = \prod p_{i} ^ {c_i}\) \(p_i\) 是个质数 。对于任意的 \(x\in N\) 均满足上述式子,也就是每个数,都能被分解成几个质数和质数的平方的乘积 。
具体证明或者其他,详见此博客

质数分布定理
\(1 \to n\) 的质数个数大约是: $ \frac{x}{\ln(x)}$ , 其数学中给出了详细且严谨的证明,\(OI\) 就不必深究其证明了

\(1.\) 试除法筛素数 ,
原理:枚举 \(1 \to n\) 这些所有的数, 同时,再用试除法 \(2\to \sqrt n\) 来判断一下第 \(i\) 个数是否为素数 ,预计复杂度 \(O(n \times \sqrt n)\)

\(2.\) 埃氏筛
原理 : 就是由于素数的倍数必然不是一个质数,那么我们在枚举到一个质数的时候,我们将它的所有倍数删除掉,那么剩下的,就是质数了 , 复杂度 : \(O(n\times \log(\log n))\)

for(int i = 2 ; i <= n ; i++) 
{
    if(!vis[i]) 
    {
        prime[++tot] = i ; 
        for(int j = i ; j * i <= n ; j++) 
        {
            vis[i * j] = 1 ;
        }
    }
}

\(3.\) 线性筛
原理和埃氏筛一致,都是删去素数的倍数从而使得剩下便是质数,那么它是埃氏筛的进一步优化。也就是让所有的数都只被访问一遍。
实现:让所有的数都只被访问一遍,也就是只被输出一遍,那么我们让它只能被它的最小质因子访问。

    for(int i = 2 ; i <= n ; i++)
    {
        //不管 i 是否为质都要筛掉其它数字 
        //从小到大枚举素数 
        for(int j = 0 ; j < tot ;j++  删去  prime * i)
        {
            int  p = prime[j] ; 
            //筛掉 i * p
            //保证p是最小i*p素因子
            if(p == 是i的最小质因子) break ; 
        }
    }

实际代码

for(int i=2;i<=n;i++)
	{
		if(!num[i])
		{
			a[cnt++]=i; //统计其中的素数
		}
		for(int j=0;j<cnt&&i*a[j]<=n;j++) 
		{
			num[i*a[j]]=1;//删除其素数的倍数
			if(i%a[j]==0)//保证是最小质因子
			{
				break;
			}
		}
	}

模板题 \(Code\)

gcd , lcm

一些约定

我们规定\(gcd(x,y)\)表示的是\(x,y\)的最大公约数,同时\(lcm(x,y)\)规定为最小公倍数。

规定\(a|b\)表示\(a\)能够乘除\(b\)
规定\(a \ \ mod \ \ b\)表示\(a\) %\(b\)

求解

\(1.\) 辗转相除法(欧几里得算法)
先来看一下其递归式

gcd(int a , int b) 
{
    return !b ? a : gcd(b , a % b) ; 
}

其复杂度是 \(O(log)\)

证明

证明 \(gcd(a , b) = gcd(b , a\text{%}b)\)
\(r = a \text{%}b , d = gcd(a , b),a = p1\times d , b = p2\times d\)
其中 \(p1,p2\) 互质(这个比较显然吧,不互质的话还有公约数,那么就不是最大公约数了 ,那么我们就可以得到
\(r = a\text{%}b = a - k \times b = p1\times d - k\times p2 \times d = (p1 - k\times p2) \times d\) , 所以首先我们可以确定 \(r\) 一定是个 \(d\) 的倍数。

感性理解一下,由于我们搞出来的\(a \text{%} b\)是单调不增的,那么我们的值一旦找到,可不就是最大的。

又因为 \(b = p2 \times d\)
我们只需说明 \(p2 , p1 - k\times p2\) 互质即可说明 \(d\) 一定为最大公约数,
证明 \(p2 , p1 - k\times p2\) 互质:
假设 \(p2 . p1 - k\times p2\) 不互质。那么我们就有

\[p2 = m\times q , p1-k\times p2 = n\times q \]

\[p1 -k\times p2 = n\times q \]

\(p2 = m\times q\) 带入可知

\[p1 - k\times m\times q = n\times q \]

\[p1 = k\times m\times q + n\times q = (k\times m+n)\times q \]

所以 \(a = p1\times d , b = p2\times d\)\(a = (k\times m + n)q \times d , b = m\times q \times d\)
\(a , b\) 的最大公约数为 \(q\times d\) , 则与假设不符,不成立,所以 \(p2 , p1-k\times p2\) 互质。所以 \(r\)\(b\) 的公约数也就是 \(d\)
所以 \(gcd(a, b) = gcd(b , a\text{%}b)\)

联系

那么 \(lcm\)\(gcd\) 有什么关系呢?

\(x = gcd(a,b)\).
则显然 \(x \mid a\),\(x\mid b\).
\(a_0 = [a\ / \ x]\ , \ b_0 = [b\ /\ x]\).
\(lcm(a_0 \ , \ b_0) = a_0 \times b_0\). \(gcd(a_0,b_0) = 1\)
\(lcm(a_0,b_0) \times gcd(a_0,b_0) \times x = a_0 \times b_0 \times x\)
又因为 ,最大公约数
所以 , \(lcm(a,b)= \frac {a \times b}{x}\)
也就是 \(lcm(a,b) \times x = a \times b\)
所以 , \(lcm(a,b) \times gcd(a,b) = a \times b\)
证毕,$over \ ~ \ $

模板题 \(Code\)

整除

【定义】: 如果\(x\) % \(y==0\) , 我们就说, \(y\)整除\(x\) ,记做(上方有约定,但是还是说一下) , \(y|x\) ,

【性质】 :(从数竞同学那里嫖来的)
1.若\(b|a\) ,则\(b|(-a) , -b|a , (-b) |(-a) , |b| \ \ | \ \ |a|\) (最后面的是两个绝对值)
2.满足转移性: 若\(a|b\) , \(b|c\) ,则\(a|c\)
3.若\(a,b,c\in Z\) ,且\(a|b , a|c\),则\(a|(b±c) , a| mb , a | mc , a | m(b±c)\),(\(mb\)代表\(m \times b\),没有骂人的意思,也不是\(mb\)那一个变量的意思,不会吧,不会吧,还有人不知道吗?)

我们可以将其进行一下推广到一般情况:

\(a_i,b_i,c_i \in Z , i = 1 , 2 , 3 … n\),并且满足\(a_i | b_i\),则有\(a|\sum\limits_{i=1}^{n} b_i \times c_i\),比较显然吧。

4.设\(a,b\in Z\),且\(a|b\) ,则对于任意的\(m \in Z\) ,都满足\(am | bm\) ,这是个充要条件。
5.若\(|a| < |b|\) , 且\(|b| \ \ | \ \ |a|\) ,则\(a = 0\)
6.若\(a,b\)互素,且\(p|\prod\limits_{i = 1}^{n} a_i\),则在\(a_1 ,a_2…a_n\)中,至少有一个\(a_i\),满足\(p\ \ | \ \ a_i\)
7.若\(a,b\)互素,且\(a|b\times c\) ,则\(a|c\)
8.\(n\)个连续整数的乘积必然能被\(n!\)整除。
9.若\(p\)为素数,对任意的正整数\(n\),都满足\(p | (n ^p - n)\).这性质叫做费马小定理,证明在求解逆元时会予以证明。

逆元

求解逆元的方法

什么叫做逆元 , 我们认为 \(a \times a^{-1} = 1 (mod \ \ p)\) ,我们称 \(a^{-1}\)\(a\)\(p\) 意义下的逆元

\(1.\) 递推求解逆元

假设 \(p = k\times i + r| i > r\)

\[k\times i + r ≡ 0 (mod \ \ p) \]

对两边同时乘上 \(i^{-1} , r^{-1}\) 就得到

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

然后就有了

\[i^{-1} ≡ - k \times r^{-1}(mod \ \ p) \]

同时,\(i > r\) ,这就形成了线性递推关系

\[f_i = -p/i \times f_{p \ \ mod \ \ i} \]

// 求 1 -> n的逆元
inv[i] = 1 ; 
for(int i = 2 ; i <= n ; i++) 
{
    inv[i] = (-p/i + p ) * f[p % i] ;
}

\(2.\) 费马小定理求解逆元。

证明费马小定理的正确性:(事实证明,证不出来背过亦可)
占个坑 , 以后证完补。

\[a^{-1} ≡ a^{p-1} (mod \ \ p) \]

然后就是一个快速幂的事,不必附代码

\(3.\) 扩欧求求解逆元。

占个坑,等讲完之后有了更深的理解再写。

逆元的应用

可以进行模意义下除法,我们在模意义下是不能进行除法的,但是我们可以利用逆元将除法转化成乘法,就行了。

为什么模意义下不能进行除法,因为会导致出现实数,而余数显示不能为小数。

扩展欧几里得算法

先证明出欧几里得显然在这里变得是比较重要。
鸣谢 : 欧几里得算法与扩展欧几里得算法_C++

引理

扩展欧几里得是用来求解线性同余方程 ,逆元,不定方程的一种算法。
引理 : 对于任意的整数 \(a,b\) ,存在 \(x,y\) 使得 \(gcd(a,b) = a\times x + b\times y\)

证明

\(b = 0\) 时 , \(gcd(a,b) = a\) , 此时 , \(x = 1 , y = 0\)
\(b\not = 0\)

\[a\times x_1 + b\times y_1 = gcd(a ,b) = gcd(b , a\text{%}b) = b\times x_2 + a\text{%}b\times y_2 \]

\[\because a\text{%}b = a - [a/b]\times b \]

\[\therefore a\times x_1 + b\times y_1 = b\times x_2 + (a - [a/b] \times b) \times y_2 \]

\[\therefore a\times x_1 + b\times y_1 = a\times y_2 + b\times (x_2 - [a/b]\times y_2) \]

\[\therefore x_1 = y_2 ,y_1 = x_2 - [a/b] \times y_2 \]

\(b = 0\) 时会得到最后的一组解,其他的均可以又上述的推导出来。

代码实现

inline void exgcd(int a , int b , int x , int y) 
{
	if(!b)
	{
		x = 1 , y = 0 ; 
		return ; 
	} 
	else 
	{
		exgcd(b , a%b , x , y) ;
		int k = x ; 
		x = y ; 
		y = k - (a / b) * y;
	}
}

没有啥模板题让着写这玩意证明的。

exgcd 求解不定方程

【鸣谢】
对于一个 \(a\times x + b\times y = c\) 这一个不定方程, \(d = gcd(a,b)\) ,那么显然的 , \(d|(a\times x + b\times y)\) , 所以,如果 \(c\text{%}d \not = 0\) , 那么就说明是无解的。如果有解的话 :
我们能够推出一组特解。
很显然,我们是有 \(a\times x_1+ b\times y_1 = d\) , 同样的,我们设 \(q \times d = c\) , 将上述式子乘以 \(q\) , 则有

\[a \times x_1\times q + b\times y_1\times q = d\times q \]

\[\therefore x_0 = x_1 \times \frac{c}{d} , y_0 = y_1 \times \frac{c}{d} \]

这样就得到一组特殊解,我们通过特殊解进行推导通解。

我们推导一般的式子,即为

\[a \times (x_0 + m) + b\times (y_0 + n) = c \]

\[a\times x_0 + a\times m + b\times y_0 + b\times n = c \]

那么我们让 \(a\times m + b\times n = 0\) ,就可以满足上述的式子了。
所以我们就有 \(a\times m = -b\times n\) , 同理可以得到 , \(m = t \times \frac{b}{a} , n = -t\times \frac{a}{b}\) , 其中 \(t\) 为任意取得。

【模板题】
\(Code\)

exgcd 求线性同余方程

关于一个模方程 \(a \times x \text{%} b = c\) 求解。
我们可以将其转化成

\[a \times x - c = b\times y \]

同理, 就可以得到

\[a\times x - b\times y = c \]

然后发现这是一个不定方程,很鸡贼,和上面一致即可。
【模板题】
\(Code\)
【青蛙的约会】
\(Code\)

posted @ 2021-01-20 22:00  SkyFairy  阅读(249)  评论(8编辑  收藏  举报