算法中常用的数学知识
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=q1B1∗q2B2∗⋅⋅⋅∗qnBn (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=q1B1∗q2B2∗⋅⋅⋅∗qnBn (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+以上是关于算法中常用的数学知识的主要内容,如果未能解决你的问题,请参考以下文章