✨博主:命运之光
✨专栏:算法基础学习
目录
✨质数
🍓(1)质数的判定——试除法
🍓(2)分解质因数——试除法
✨约数
🍓(1)试除法求一个数的所有约数
🍓(2)约数个数
🍓(3)约数之和
🍓(4)欧几里得算法(辗转相除法)
前言:算法学习笔记记录日常分享,需要的看哈O(∩_∩)O,感谢大家的支持!
✨质数
🍓所有大于1的自然数,所有<=1的数既不是质数也不是合数
定义:在大于1的整数中,如果只包含1和本身这两个约数,就被称为质数,或者叫素数
🍓(1)质数的判定——试除法
质数的一个重要性质:如果d能整除n,显然n除d也能整除n
故发现n的所有的约数都是成对出现的(d与n/d都成成对出现的)
所以枚举时可以只枚举每一对当中较小的那一个,枚举:
🍓试除法判定质数:
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
return false;
return true;
}
🍓(2)分解质因数——试除法
从小到大枚举所有数
🍓试除法分解质因数:
void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
if (x > 1) cout << x << ' ' << 1 << endl;
cout << endl;
}
🍓筛
罗列出每个数,依次删除每个数的倍数,剩下的数就是质数,可以对此进行优化,可以不删每一个数的倍数, 可以只删质数的倍数,这样就不用重复删。
🍓质数定理:
优化完的筛法:埃氏筛法
🍓朴素筛法求素数:
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (st[i]) continue;
primes[cnt ++ ] = i;
for (int j = i + i; j <= n; j += i)
st[j] = true;
}
}
🍓线性筛法:
把每一个合数用它的某个质因子筛掉
每个数都会被其最小质因子筛掉,而且每个数只有一个最小质因子,故每个数只会被筛一次
🍓线性筛法求素数:
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
✨约数
约数
🍓(1)试除法求一个数的所有约数
🍓试除法求所有约数:
vector<int> get_divisors(int x)
{
vector<int> res;
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0)
{
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(), res.end());
return res;
}
🍓(2)约数个数
🍓(3)约数之和
约数个数和约数之和:
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
🍓(4)欧几里得算法(辗转相除法)
🍓欧几里得算法:
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a; // <表达式1>?<表达式2>:<表达式3>,
} //它的意思是,如果表达式1成立,则输出表达式2的值,否则输出表达式3的值
补充小知识:
两个数的积等于它们最大公约数和它们最小公倍数的
积。公式表示为 :a×b=gcd(a,b)×lcm(a,b)
🍓最小公倍数与最大公约数模板: