简单数学

博主整理了一下\(OI\)中简单的数论知识,故取名简单数学,以后会随着学习的深入慢慢扩展开来。

以下的代码部分没经过验证,可能一定会出锅

质数

质数的判定

顾名思义就是判定某一个数是不是质数

试除法

一个结论:

若一个正整数\(N\)为合数,那么一定存在一个正整数\(T\)能够整除\(N\),且\(2\le N \le \sqrt{N}\)

该结论可以通过反证法证明,这里不再赘述(直接背过他不香吗?)

bool judge_prime(int N){
    for(int i=2;i*i<=N;++i)
        if(N%i==0) return 0;
    return 1;
}

容易看出复杂度为\(O(\sqrt{N})\)

质数的筛选

顾名思义就是晒出出\(1\backsim N\)中的质数

Eratosthenes筛法

核心思想就是质数的倍数是合数,具体不再赘述

void primes(int n){
    memset(v,0,sizeof(v));
    for(int i=2;i<=n;++i)
    {
        if(v[i]) continue;
        prime[++cnt]=i;//i是质数
        for(int j=i*2;j<=n;j+=i) v[j]=1;
	}
}

复杂度为\(O(\sum_{质数p\le \frac{N}{p}})=O(N\ \log \log N)\)

线性筛法

核心思想就是通过“从小到大积累质因子”的方式来标记合数,以此来避免\(Eratosthenes\)筛法重复标记合数的问题

具体实现原理简单来说就是:每个合数\(i*p\)只会被它的最小质因子筛一次

void primes(int n){
	memset(v,0,sizeof(v));//最小质因子
    cnt=0;//质数的数量
    for(int i=2;i<=n;++i)
    {
        if(v[i]==0) {prime[++cnt]=i;v[i]=i;}
        for(int j=1;j<=m;++j)
        {
            if(prime[j]>v[i]||prime[j]>n/i) break;
            v[i*prime[j]]=1;
        }
    }
}

复杂度为\(O(N)\)我一般都是用埃氏筛

算术基本定理

任何一个大于\(1\)的正整数都能被唯一分解为有限个质数的乘积的形式,写作:

\[N=p_1^{c_1}p_2^{c_2}...p_m^{c_m} \]

其中\(c_i\in\N^+\),\(p_i\)都是质数,且满足\(p_1<p_2<...<p_m\)

试除法分解质因数

就是结合一下埃氏筛和试除法

void divide(int n)
{
    cnt=0;
    for(int i=2;i*i<=n;++i)
    {
        if(n%i==0)
        {
            p[++cnt]=i;c[cnt]=0;
            while(n%i==0) n/=i,c[cnt]++;
		}
    }
    if(n>1) p[++cnt]=n,c[cnt]=1;
}

复杂度为\(O(\sqrt{N})\)

约数

算术基本定理的推论

如果一个正整数被分解成了\(N=p_1^{c_1}p_2^{c_2}...p_m^{c_m}\)这种形式,则\(N\)的正约数集合可以写作

\(p_1^{b_1}p_2^{b_2}...p_m^{b_m}\)其中\(0\le b_i \le c_i\)

约数个数

\(N\)的正约数个数为\(\prod\limits_{i=1}^m(c_i+1)\)

约数和

\(N\)的所有正约数和为\(\prod\limits_{i=1}^m(\sum\limits_{j=0}^{c_i}(p_i)^j)\)

\(N\)的正约数集合

试除法

核心就是利用约数总是成对出现(除了对于完全平方数,\(\sqrt{N}\)会单独出现)

for(int i=1;i*i<=N;++i)
{
    if(n%i==0)
    {
        d[++cnt]=i;
        if(i!=n/i) d[++cnt]=n/i;
	}
}

复杂度为\(O(\sqrt{N})\)

试除法的推论

一个正整数的约数个数上界为\(2\sqrt{N}\)

倍数法

\(1\backsim N\)中每个数的正约数集合

核心思路就是对于每个约数\(d\),以它为约数的正整数为\(d,2d,3d...\left\lfloor\dfrac{N}{d}\right\rfloor*d\)

for(int i=1;i<=n;++i)
	for(int j=1;j<=n/i;++j)
        f[i*j].push_back(i);

复杂度为\(O(N+\frac{N}{2}+\frac{N}{3}...+\frac{N}{N})=O(N\log N)\)

倍数法推论

\(1\backsim N\)中每个数的约数个数的总和大约为\(N \log N\)

最大公约数

定理

\(\forall a,b\in \N \ \ \ \gcd(a,b)*lcm(a,b)=a*b\)

更相减损法

\(\forall a,b\in \N,a\ge b \ \ \ \ \gcd(a,b)=\gcd(b,a-b)=\gcd(a,a-b)\)

\(\forall a,b\in \N \ \ \ \gcd(2a,2b)=\gcd(a,b)\)

如果需要高精度计算时,高精度除法(取模)很恶心人,可以用更相减损法来替代欧几里得算法

欧几里得法

\(\forall a,b\in \N \ \ \ \gcd(a,b)=\gcd(b,a\%b)\)

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

互质与欧拉函数

欧拉函数

定义

\(1\backsim N\)中与\(N\)互质的数的个数,记为\(\varphi(N)\)

$\varphi(N)=N*\prod\limits_{质数p|N}(1-\frac{1}{N}) $

积性函数

如果\(a,b\)互质时,有\(f(ab)=f(a)*f(b)\),那么函数\(f\)就是积性函数

积性函数的性质

\(f\)是积性函数,且在算术基本定理中\(n=\prod_{i=1}^mp_i^{c_i}\)\(f(n)=\prod_{i=1}^{m}f(p_i^{c_i})\)

欧拉函数基本性质
  1. \(\forall\ n>1,1\backsim n\)中与\(n\)互质的数的和为\(n*\varphi(n)/2\)
  2. \(a,b\)互质,则\(\varphi(ab)=\varphi(a)*\varphi(b)\)(积性函数的性质)
  3. \(p\)是质数,若\(p\mid n\)\(p^2\mid n\),则\(\varphi(n)=\varphi(n/p)*p\)
  4. \(p\)是质数,若\(p\mid n\)但是\(p^2 \nmid n\)\(\varphi(n/p)*(p-1)\)
  5. \(\sum_{d\mid n}\varphi(d)=n\)

猜你喜欢

转载自www.cnblogs.com/pyyyyyy/p/12762576.html