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

🎬 博主名称个人主页

🔥 个人专栏 : 《算法通关》《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));
	 }
}
相关推荐
放下华子我只抽RuiKe54 小时前
算法的试金石:模型训练、评估与调优的艺术
人工智能·深度学习·算法·机器学习·自然语言处理·数据挖掘·线性回归
oem1104 小时前
C++中的享元模式实战
开发语言·c++·算法
流云鹤4 小时前
每日一题0316
算法
leonkay4 小时前
Golang语言闭包完全指南
开发语言·数据结构·后端·算法·架构·golang
颜酱5 小时前
BFS 与并查集实战总结:从基础框架到刷题落地
javascript·后端·算法
casual~5 小时前
第?个质数(埃氏筛算法)
数据结构·c++·算法
仰泳的熊猫6 小时前
题目2308:蓝桥杯2019年第十届省赛真题-旋转
数据结构·c++·算法·蓝桥杯
hssfscv6 小时前
力扣练习训练2(java)——二叉树的中序遍历、对称二叉树、二叉树的最大深度、买卖股票的最佳时机
java·数据结构·算法
y = xⁿ7 小时前
【LeetCodehot100】二叉树大合集 T94:二叉树的中序遍历 T104:二叉树的最大深度 T226:翻转二叉树 T101:对称二叉树
后端·算法·深度优先
不想看见4047 小时前
Search a 2D Matrix II数组--力扣101算法题解笔记
数据结构·算法