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

🎬 博主名称个人主页

🔥 个人专栏 : 《算法通关》《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));
	 }
}
相关推荐
近津薪荼2 小时前
dfs专题——二叉树的深搜3(二叉树剪枝)
c++·学习·算法·深度优先
伯明翰java2 小时前
排序算法(1)
算法·排序算法
啊阿狸不会拉杆2 小时前
《机器学习导论》第 2 章-监督学习
数据结构·人工智能·python·学习·算法·机器学习·监督学习
乌萨奇也要立志学C++2 小时前
【洛谷】记忆化搜索 原理剖析与经典例题详解
算法·深度优先
Code920072 小时前
洛谷P3514 [POI 2011] LIZ-Lollipop(思维题)
算法
m0_706653232 小时前
C++中的解释器模式
开发语言·c++·算法
We་ct2 小时前
LeetCode 202. 快乐数:题解+思路拆解
前端·算法·leetcode·typescript
hetao17338372 小时前
2026-01-29~02-03 hetao1733837 的刷题记录
c++·笔记·算法
咩咩不吃草2 小时前
决策树三大核心算法详解:ID3、C4.5与CART
算法·决策树·机器学习