数论初步

来源:互联网 发布:oracle sql 优化 分析 编辑:程序博客网 时间:2024/06/03 21:53

一、唯一分解定理

基本描述

任何一个大于1的自然数N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积.

理解

换句话说,它来指导我们分解质因数
想想在分解质因数的时候,我们使用的是短除法,先试除2,然后试除3,其实就是用到的唯一分解定理。

代码

找出num的所有质因数

void findfactor(int num){    v.clear();    int i = 2;    while(num != 1){        if(num % i == 0){            v.push_back(i);            while(num % i==0) num/=i;        }        ++i;    }}

二、欧几里得算法

基本描述

当我们需要算出两个数字的最大公约数,就要用到欧几里得算法。
这个算法不需要过多介绍了。

代码

int gcd(int a, int b){    if(!b) return a; else return gcd(b,a%b);}

拓展

那么最小公倍数呢?
lcm(a,b) = a * b/gcd(a,b)
但是要注意,在a,b很大的时候,即使使用的是long long,a*b是有溢出的风险的,
所以最好写成:
lcm(a,b) = a/gcd(a,b) * b
即先除再乘,防止溢出。

三、素数筛法

Eratosthenes 筛法

首先在[1,nmax]筛掉2的所有倍数,然后从筛掉3的倍数,再筛掉4的倍数……,一直到sqrt(nmax+0.5)。

但是会发现,有些数字被筛了两次,如8在筛2倍数的时候筛掉一次,筛4倍数的时候筛掉一次,这样效率会大大低下。

解决方案就是,在选择被筛倍数的数字的时候,先判断一下是否被筛掉,若没被筛掉再继续。

代码

void prime(){    memset(isprime,1,sizeof isprime);    for(int i = 2;i<=(int)(sqrt(nmax+0.5));++i){        if(isprime[i])            for(int j = 2;i*j<nmax;++j)                 isprime[i*j] = false;    }}

欧拉线性筛

对于处理素数,还有更高效的线性筛法,在学习了欧拉函数之后,再来讲解。

素数定理

π(x) = x/lnx

四、拓展欧几里得

基本描述

找出一对整数(a,b),使得ax+by = gcd(a,b),其中x,y不一定是正数,也有可能是负数或零。那么如何实现呢?

代码实现

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

拓展

按照如上的代码,就可以求得一组可行解(x1,x2)。
如果需要求解其他解,如何实现呢?

我们可以做到的是,求出另外一组可行解(x2,y2),并且可以得出以下等式
ax1 + by1 = ax2 + by2, 他们都等于gcd(a,b).
通过简单的变形,可以进一步得到a(x1-x2) = b(y2-y2),并且假设gcd(a,b) = g
方程式两边同时除以g,可以得到(a/g) * (x1-x2) = (b/g) * (y2-y1).
令 a’ = a/g, b’ = b/g, 不难得到a’与b’是互质的,进一步得到
a’(x1-x2) = b’(y2-y1) ,由于a’与b’互质,所以(x1-x2) 一定是b’的整数倍,令(x1-x2)/b’ = k, 从而得到
y2-y1 = ka’ ,进而得出以下结论

结论1

若已经求解出ax+by = c的一组整数解为(x0,y0),则其任意解都可以写成(x0+kb’,yo-ka’)的形式,其中,a’ = a/gcd(a,b),b’ = b/gcd(a,b),k为任意整数。

结论2

对于方程ax+by = c来说:
设a,b,c为任意整数,g = gcd(a,b),方程ax+by = g的一组解是(x0,y0),则当c是g的倍数的时候,ax+by = c的一组解是(x0 * c / g , y0 * c / g).若c不是g的倍数的时候无整数解。

举例

  1. 求解6x+15y=9,根据欧几里得算法,得到一组解为(-2,1),满足-2 * 6 + 1 * 15 = 3,由于9是3的倍数,将系数成3即可,即 -6 * 6 + 3 * 15 = 9.
  2. 求解6x+15y=8, 8不是3的倍数,无整数解。

五、模运算

基本描述

当计算的结果非常大时,题目经常要求输出对某一个素数取模后的结果,在计算的过程当中就涉及到,如何进行模运算。模运算可分为,加法模,减法模,乘法模和乘方模。

公式

加法模

(a+b) mod n = ((a mod n) + (b mod n)) mod n

减法模

(a - b) mod n = ((a mod n) - (b mod n) + mod) mod n

乘法模

ab mod n = (a mod n) (b mod n) mod n

乘方模

乘方模看做是多次对乘法模的运算即可

六、快速幂

基本描述

(之前写过一篇ppt,就直接拿来用了)
这里写图片描述

这里写图片描述

实现代码

(同时对m取模)

int ans = 1; while(n){        if(n&1) ans = ans * base % m;        n >>= 1;        base = ((base%m)*(base%m))%m;}

七、同余与模线性方程

基本描述

先来看看韩信点兵的故事:
韩信带1500名兵士打仗,战死四五百人,站3人一排,多出2人;站5人一排,多出4人;站7人一排,多出6人。韩信很快说出人数:1049。
设总人数为a,可以得出:
a ≡ 2(mod 3)
a ≡ 4(mod 5)
a ≡ 6(mod 7)
其中≡的意思是同余,即a mod 3 = 2 mod 3, a mod 5 = 4 mod 5, a mod 7 = 6 mod 7.

同余定理

定理1

如果a ≡ b (mod m), 则 m|(a-b),其中|表示整除。
例如: 73 ≡ 23 (mod 10), 则有 10 | (73 - 23).

定理2

如果 a ≡ b (mod m), c ≡ b (mod m), 则 a ± c ≡ b ± d (mod m)
例如 73 ≡ 3 (mod 10), 84 ≡ 4 (mod 10) , 则有 73 ± 84 ≡ 3 ± 4 (mod 10)

定理3

如果 a ≡ b (mod m), c ≡ b (mod m), 则 a × c ≡ b × d (mod m)
例如 73 ≡ 3 (mod 10), 84 ≡ 4 (mod 10) , 则有 73 × 84 ≡ 3 × 4 (mod 10)

定理4

如果 a ≡ b (mod m), a^n ≡ b^n (mod m)
例如 40 ≡ 1 (mod 13), 则有 40^2 ≡ 1^2 (mod 13)