约数

144 阅读1分钟

约数

试除法求所有约数

  • C++
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;
}
  • Java
public static TreeSet<Integer> get_divisors(int x) {
    TreeSet<Integer> res = new TreeSet<>();
    for (int i = 1; i <= x / i; i++) {
        if (x % i == 0) {
            res.add(i);
            res.add(x / i);
        }
    }
    return res;
}

约数个数与约数之和

  • 如果 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^)

求最大公约数(欧几里得算法/辗转相除法)

  • 核心:(a, b) = (a, (a mod b))

  • C++

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

练习

01 试除法求约数

  • 题目

Snipaste_2023-04-23_18-28-47.png

  • 题解
import java.io.*;
import java.util.*;

public class Main {
    public static int n;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        n = Integer.parseInt(br.readLine());

        while (n-- > 0) {
            int x = Integer.parseInt(br.readLine());

            TreeSet<Integer> res = get_divisors(x);

            res.forEach(o -> pw.print(o + " "));
            pw.println();
        }

        pw.close();
        br.close();
    }

    public static TreeSet<Integer> get_divisors(int x) {
        TreeSet<Integer> res = new TreeSet<>();

        for (int i = 1; i <= x / i; i++) {
            if (x % i == 0) {
                res.add(i);
                res.add(x / i);
            }
        }

        return res;
    }
}

02 约数个数

  • 题目

Snipaste_2023-04-23_19-27-37.png

  • 题解
import java.io.*;
import java.util.*;

public class Main {
    public static final int mod = (int) 1e9 + 7;
    public static int n;
    //存输入的所有数的质数出现的个数
    public static Map<Integer, Integer> primes = new HashMap<>();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        n = Integer.parseInt(br.readLine());

        while (n-- > 0) {
            int x = Integer.parseInt(br.readLine());
            //试除法分解质因数
            for (int i = 2; i <= x / i; i++) {
                while (x % i == 0) {
                    //jdk8 新的方法 获取键对应的值 如果键不存在 返回预先设定的值
                    primes.put(i, primes.getOrDefault(i, 0) + 1);
                    x /= i;
                }
            }
            if (x > 1) {
                primes.put(x, primes.getOrDefault(x, 0) + 1);
            }
        }

        long res = 1;
        for (Integer o : primes.values()) {
            res = res * (o + 1) % mod;
        }
        pw.println(res);
        pw.close();
        br.close();
    }
}

03 约数之和

  • 题目

Snipaste_2023-04-23_19-44-10.png

  • 题解
import java.io.*;
import java.util.*;

public class Main {
    public static final int mod = (int) 1e9 + 7;
    public static int n;
    //存输入的所有数的质数出现的个数
    public static Map<Integer, Integer> primes = new HashMap<>();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        n = Integer.parseInt(br.readLine());

        while (n-- > 0) {
            int x = Integer.parseInt(br.readLine());
            //试除法分解质因数
            for (int i = 2; i <= x / i; i++) {
                while (x % i == 0) {
                    //jdk8 新的方法 获取键对应的值 如果键不存在 返回预先设定的值
                    primes.put(i, primes.getOrDefault(i, 0) + 1);
                    x /= i;
                }
            }
            if (x > 1) {
                primes.put(x, primes.getOrDefault(x, 0) + 1);
            }
        }

        long res = 1;
        //约数之和: (p~1~^0^ + p~1~^1^ + ... + p~1~^c1^) * ... * (p~k~^0^ + p~k~^1^ + ... + p~k~^ck^)
        for (Integer a : primes.keySet()) {
            //a指的是上面的p  b指的是上面的c
            int b = primes.get(a);
            //t指的是每一个(p~k~^0^ + p~k~^1^ + ... + p~k~^ck^)
            long t = 1;
            while (b-- > 0) {
                //秦九韶算法
                t = (t * a + 1) % mod;
            }
            res = res * t % mod;
        }
        pw.println(res);
        pw.close();
        br.close();
    }
}

04 最大公约数

  • 题目

Snipaste_2023-04-23_19-55-28.png

  • 题解
import java.io.*;
import java.util.*;

public class Main {
    public static int n;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        n = Integer.parseInt(br.readLine());

        while (n-- > 0) {
            String[] str = br.readLine().split(" ");
            pw.println(gcd(Integer.parseInt(str[0]), Integer.parseInt(str[1])));
        }
        pw.close();
        br.close();
    }

    public static int gcd(int a, int b) {
        return b != 0 ? gcd(b, a % b) : a;
    }
}