数学知识:约数的详细解析

🎬 博主名称个人主页

🔥 个人专栏 : 《算法通关》《Java讲解》

⛺️心简单,世界就简单

序言

讲一下约数,平时做题时候还是经常会出现的,比如求两个数的最大公约数,求一个数的因数个数
目录

🎠序言

🎠试除法求约数

🎠约数个数

🎃内容讲解

🎃公式总结

🎠约数之和

🎠欧几里得算法


试除法求约数

因为约数也是成对出现的,比如2 * 6 = 12,我们就只用求出来2后然后直接把12 / 2也push_back()里面就行,所以我们的循环条件是到n / i

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const int N = 1e6 +10; 

vector<int> get_divisors(int n){
	vector<int> res;
	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 res;
}


int main(){
	int n;
	cin >> n;
	
	while(n --){
		int x;
		cin >> x;
		auto res = get_divisors(x);
		for(auto t : res) cout << t << ' ';
		cout <<endl;
	}
}

约数个数

内容讲解

如果我直接拿公式可能看不大懂,所以我就先举个例子

eg.求12的约数个数

第一步: 分解成质数相乘的样子:12 = 2 × 2 × 3 = 2² × 3¹

**第二步:**理解约数是怎么来的L:

  • 对于质数2:有3种选择

    • 选0个2(就是1)

    • 选1个2(就是2)

    • 选2个2(就是4)

  • 对于质数3:有2种选择

    • 选0个3(就是1)

    • 选1个3(就是3)

**第三步:**比喻一下

  • 上衣有3种选择(2⁰, 2¹, 2²)

  • 裤子有2种选择(3⁰, 3¹)

总搭配数 = 3 × 2 = 6 种

总结

这6种搭配就是12的所有约数:

1 = 2⁰ × 3⁰

2 = 2¹ × 3⁰

3 = 2⁰ × 3¹

4 = 2² × 3⁰

6 = 2¹ × 3¹

12 = 2² × 3¹


公式总结

如果一个数分解成:质数1^a × 质数2^b × 质数3^c × ...

那么约数个数 = (a+1) × (b+1) × (c+1) × ...

我们拿个题来看一下

这道题让我求一堆数相乘后的约数,笨方法当然是先相乘之后再求质数个数,但我们实际上可以直接用一个哈希表记录一下每个数的质数然后++就行

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>

using namespace std;

typedef long long LL;

const int mod = 1e9 +7; 


int main(){
	int n;
	cin >> n;
	
	unordered_map<int, int> primes;
	while(n --){
		int x;
		cin >> x;
	for(int i = 2; i <= x / i; i ++){
		while(x % i == 0) {
			x /= i;
			primes[i] ++ ;
		}
	
	}
		if(x > 1) primes[x] ++ ;
	}
	
	LL res = 1;
	for(auto prime : primes) res = res * (prime.second + 1) % mod;
	
	cout << res;
	
}

约数之和

这个求和其实我感觉很妙

就是我们上面不是得到了约数之和吗,然后我们还拿这个12来看

12 = 2 × 2 × 3 = 2² × 3¹

约数为 1 2 3 4 6 12 ,那么和就是28了

我们还可以发现(1 + 2 + 4) * (1 + 3)= 28

然后我们的结论就是求出质因数的和然后相乘,就是下面这一步

cpp 复制代码
	int p = prime.first, a = prime.second;
		LL t = 1;
		while(a --){
			t = (t * p + 1) % mod;
		
		}
cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>

using namespace std;

typedef long long LL;

const int mod = 1e9 +7; 


int main(){
	int n;
	cin >> n;
	
	unordered_map<int, int> primes;
	while(n --){
		int x;
		cin >> x;
	for(int i = 2; i <= x / i; i ++){
		while(x % i == 0) {
			x /= i;
			primes[i] ++ ;
		}
	
	}
		if(x > 1) primes[x] ++ ;
	}
	
	LL res = 1;
	for(auto prime : primes){
		int p = prime.first, a = prime.second;
		LL t = 1;
		while(a --){
			t = (t * p + 1) % mod;
		
		}
			res = res * t % mod;
	}
	
	cout << res;
	
}

欧几里得算法

就是求最大公约数,这个大家都会就不详细说明了,就是辗转相除法,当b=0时候,就直接返回a的值就行

cpp 复制代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>

using namespace std;

typedef long long LL;

const int mod = 1e9 +7; 

int gcd(int a, int b){
	return b ? gcd(b, a % b) : a;
} 

int main(){
	int n;
	 scanf("%d", &n);
	 while(n --){
	 	int a, b;
	 	scanf("%d%d", &a, &b);
	 	printf("%d\n", gcd(a, b));
	 }
}
相关推荐
独自破碎E15 小时前
【DFS】BISHI76 迷宫寻路
算法·深度优先
寄存器漫游者15 小时前
Linux 线程间通信
数据库·算法
岛雨QA15 小时前
查找算法「Java数据结构与算法学习笔记7」
数据结构·算法
宝贝儿好15 小时前
【强化学习】第十章:连续动作空间强化学习:随机高斯策略、DPG算法
人工智能·python·深度学习·算法·机器人
isyoungboy16 小时前
从图像中提取亚像素边缘点
算法
郝学胜-神的一滴16 小时前
深入理解链表:从基础到实践
开发语言·数据结构·c++·算法·链表·架构
岛雨QA16 小时前
排序算法「Java数据结构与算法学习笔记6」
数据结构·算法
熬夜有啥好16 小时前
Linux软件编程——综合小练习
linux·算法·目录遍历·fgets·strcpy·linux内核与用户交互·strtok
民乐团扒谱机16 小时前
【硬核解析】网易云听歌/哼歌识曲底层技术:从算法实现到工程落地(附核心公式/伪代码)
算法
Z9fish16 小时前
sse哈工大C语言编程练习23
c语言·数据结构·算法