约数相关算法主要内容
- 一、基本思路
-
- 1、定义
- 2、试除法——求一个数的所有约数
- 3、约数个数
- 4、约数之和
- 5、欧几里得算法——辗转相除法(求解最大公约数)
- 二、Java、C语言模板实现
- 三、例题题解
一、基本思路
1、定义
- 约数:
-
- 约数是指一个数(因数)能整除另一个数的正整数,也称为因数。
- 举例:
-
- “||”表示整除,a||b,即为 a 整除 b ,则,b/a为一个整数。
2、试除法——求一个数的所有约数
- (d || n) ==> (n/d || n) ==> (d <= n/d) ==> (d <= sqrt(n))
- 其中 d 与 n/d 都是 n 的约数,并且成对出现,我们需要成对储存
- 但是需要特判一种情况—— i ?= n/i
3、约数个数
- 质因数(正整数)分解定理:

- 约数个数定理:

- 问题:是否可以用试除法求解约数个数?
-
- 理论上暴力求解可以,但是稍微大一点的数就会极容易溢出。
4、约数之和
- 约数之和定理:

- 求解技巧:

5、欧几里得算法——辗转相除法(求解最大公约数)
- 基本性质:
-
- (d||a , d||b) ⇒ (d||ax+by);
- 核心原理:
-
-
- 欧几里得算法原理证明:

二、Java、C语言模板实现
static void getDiv(int n){
PriorityQueue<Integer> q = new PriorityQueue<Integer>();
int count = 0;
for(int i = 1; i <= n/i; i++){
if(n % i == 0){
q.add(i);
count++;
if(i != n/i){
q.add(n/i);
count++;
}
}
}
for(int i = 0; i < count; i++){
System.out.print(q.poll() + " ");
}
}
for(int ii = 0; ii < n; ii++){
int x = Integer.parseInt(reader.readLine());
for(int i = 2; i <= x/i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1){
map.put(x, map.getOrDefault(x, 0) + 1);
}
}
long res = 1;
for(int value : map.values()){
res = res * (value + 1) % Mod;
/ 此处一边相乘,一边mod,是因为一旦数字变大,就会导致溢出,影响最后的结果
}
for(int ii = 0; ii < n; ii++){
int x = Integer.parseInt(reader.readLine());
for(int i = 2; i <= x/i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1){
map.put(x, map.getOrDefault(x, 0) + 1);
}
long res = 1;
for(int key : map.keySet()){
long t = 1;
int value = map.get(key);
while(value-- > 0){
t = (t * key + 1) % Mod;
}
res = res*t % Mod;
}
static int gcd(int a, int b){
return b != 0 ? gcd(b, a % b) : a;
}
试除法求所有约数 —— 模板题 AcWing 869. 试除法求约数
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;
}
约数个数和约数之和 —— 模板题 AcWing 870. 约数个数, AcWing 871. 约数之和
如果 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)
欧几里得算法 —— 模板题 AcWing 872. 最大公约数
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
三、例题题解

import java.util.*;
public class Main{
static void getDiv(int n){
PriorityQueue<Integer> q = new PriorityQueue<Integer>();
int count = 0;
for(int i = 1; i <= n/i; i++){
if(n % i == 0){
q.add(i);
count++;
if(i != n/i){
q.add(n/i);
count++;
}
}
}
for(int i = 0; i < count; i++){
System.out.print(q.poll() + " ");
}
System.out.println();
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for(int i = 0; i < n; i++){
int ai = in.nextInt();
getDiv(ai);
}
}
}

import java.util.*;
import java.io.*;
public class Main{
static long Mod = (long)1e9 + 7;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
HashMap<Integer,Integer> map = new HashMap<>();
int n = Integer.parseInt(reader.readLine());
for(int ii = 0; ii < n; ii++){
int x = Integer.parseInt(reader.readLine());
for(int i = 2; i <= x/i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1){
map.put(x, map.getOrDefault(x, 0) + 1);
}
}
long res = 1;
for(int value : map.values()){
res = res * (value + 1) % Mod;
}
System.out.println(res);
}
}

import java.util.*;
import java.io.*;
public class Main{
static long Mod = (long)1e9 + 7;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
HashMap<Integer,Integer> map = new HashMap<>();
int n = Integer.parseInt(reader.readLine());
for(int ii = 0; ii < n; ii++){
int x = Integer.parseInt(reader.readLine());
for(int i = 2; i <= x/i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1){
map.put(x, map.getOrDefault(x, 0) + 1);
}
}
long res = 1;
for(int key : map.keySet()){
long t = 1;
int value = map.get(key);
while(value-- > 0){
t = (t * key + 1) % Mod;
}
res = res*t % Mod;
}
System.out.println(res);
}
}

import java.util.*;
import java.io.*;
public class Main{
static int gcd(int a, int b){
return b != 0 ? gcd(b, a % b) : a;
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine());
for(int i = 0; i < n; i++){
String[] str = in.readLine().split(" ");
int a = Integer.parseInt(str[0]);
int b = Integer.parseInt(str[1]);
System.out.println(gcd(a, b));
}
}
}