算法中常用的数学知识

Posted JunMain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法中常用的数学知识相关的知识,希望对你有一定的参考价值。

算数基本定义

任何一个合数都可以写成,若干个质数相乘

n = q 1 B 1 ∗ q 2 B 2 ∗ ⋅ ⋅ ⋅ ∗ q n B n n = q_1^{B_1} * q_2^{B_2} * ···*q_n^{B_n} n=q1B1q2B2qnBn (n是一个合数, q i q_i qi是质数)

因此只要是一个合数我们就可以分解质因数,并且 n最多只有一个大于 n \\sqrt{n} n 的质因子

分解质因数 O ( n ) O(\\sqrt{n}) O(n )

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
    cin >> n;
    
    for (int i = 2; i <= n / i; i ++)
    {
        if (n % i == 0)
        {
            int s = 0;
            while (n % i == 0)
            {
                n /= i;
                s ++;
            }
            cout << i << " " <<  s << endl;
        }
    }
    
    if (n > 1)	cout << n << " " << 1 << endl;
    
	return 0;
}

质数

质数是除了1和本身外不能被其他数字整除的数字


试除法 O ( n ) O(\\sqrt{n}) O(n )

#include<bits/stdc++.h>
using namespace std;

bool is_prime(int n)
{
	if (n < 2) return false;
    
	for (int i = 2; i <= n / i; i ++)
        if (n % i == 0 )	return false;
    
    return true;
}


int main()
{
    int n;
    cin >> n;
    
    cout << is_prime(n);    
    
    return 0;
}

朴素筛法求质数 ( n l o g n ) (nlog_n) (nlogn)

利用筛法可以求出1 - n中的所有素数, 可以进行预处理

基本思路:把所有数字的倍数删掉,剩下的数字就是质数

#include<bits/stdc++.h>
using namespace std;

const int N = 1000010;

bool st[N];
int prime[N], cnt;

int main()
{
    int n;
    cin >> n;
    
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i])
            prime[cnt ++] = i;
        for (int j = i; j <= n; j += i)		st[i] = true;
    }
    
    return 0;
}


埃式筛法 O ( n l o g l o g n ) O(nlog_{log_n}) O(nloglogn) ~ O ( n ) O(n) O(n)

一个埃及人发明的筛法

根据算数基本定理:任何一个合数都是有若干个质数相乘,

我们可以优化上面的朴素筛法,每次去掉质数的倍数, 最后剩下的一定是素数

#include<bits/stdc++.h>
using namespace std;

const int N = 100010;

bool st[N];
int prime[N], cnt;

int main()
{
    int n;
    cin >> n;
   
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i])
        {
            prime[cnt ++] = i;
            for (int j = i; j <= n; j += i)		st = true;
        }
    return 0;
}


线性筛法 O ( n ) O(n) O(n)

线性筛法的核心原理: 一个合数n只会被它的最小质因子筛掉

#include<bits/stdc++.h>
using namespace std;

const int N = 1000010;

bool st[N];
int prime[N], cnt;


int main() 
{
    int n;
    cin >> n;
    
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i])		prime[cnt ++] = i;
        
        for (int j = 0; prime[j] <= n / i; j ++)	//从小到大枚举所有质数
        {
            st[prime[j] * i] = true;			//i%p[j]!=0	 p[j]一定小于i的所有质因子一定是 p[j]*i 的最小质因子
            if (i % prime[j] == 0)	break;		//i%p[j]==0  p[j]此时一定是i的最小质因子
        }
    }
        
    return 0;
}


约数

试除法求约数 O ( n ) O(\\sqrt{n}) O(n )

n n n 的约数

#include<bits/stdc++.h>
using namespace std;

vector<int> res;

int main()
{
    int n;
    cin >> n;
    
    for (int i = 1; i <= n / i; i ++)
    {
        if (n % i == 0)
        {
            res.push_back(i);
            if (i != n / i )	res.push_back(n / i);	//特判 平方
        }
    }
    
    sort(res.begin(), res.end());
    
    
    return 0;
}


求约数个数 O ( n ) O(\\sqrt{n}) O(n )

算数基本定理: n = q 1 B 1 ∗ q 2 B 2 ∗ ⋅ ⋅ ⋅ ∗ q n B n n = q_1^{B_1} * q_2^{B_2} * ···*q_n^{B_n} n=q1B1q2B2qnBn (n是一个合数, q i q_i qi是质数)

公式: n的约数个数 = ( B 1 + 1 ) ∗ ( B 2 + 1 ) ∗ ⋅ ⋅ ⋅ ∗ ( B n + 1 ) (B_1 + 1)*(B_2 + 1)*···*(B_n + 1) (B1+1)(B2+以上是关于算法中常用的数学知识的主要内容,如果未能解决你的问题,请参考以下文章

数学建模基础知识

7天掌握数模常用算法应用与Matlab编程

csp-j/s考试内容

PASCAL算法知识题~~高分~紧急~

干货||数学建模中常用算法及程序

算法介绍导引