目录
一、试除法求约数
试除法求约数本质上还是暴力枚举,但是依然可以通过 乘法原理分解 把时间复杂度降到根号n,思想很淳朴,这里直接给出代码:
给定 nn 个正整数 aiai,对于每个整数 aiai,请你按照从小到大的顺序输出它的所有约数。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个整数 aiai。
输出格式
输出共 nn 行,其中第 ii 行输出第 ii 个整数 aiai 的所有约数。
数据范围
1≤n≤1001≤n≤100,
2≤ai≤2×1092≤ai≤2×109输入样例:
2 6 8
输出样例:
1 2 3 6 1 2 4 8
import java.util.*;
public class Main{
public static void get_divisors(int x) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= x / i; i ++) { //循环一定要从1开始,因为1百分之一百是约数
if (x % i == 0) { // 如果这个数是约数,就把它加到list中
list.add(i);
if (i != x / i) list.add(x / i); //如果是约数,那它的另一个约数不同的话就加入list
}
}
Collections.sort(list);
for (int i :list) {
System.out.print(i+" ");
}
System.out.println();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while (n -- > 0) {
int i = sc.nextInt();
get_divisors(i);
}
}
}
二、约数个数
基本思想 :
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
给定 nn 个正整数 aiai,请你输出这些数的乘积的约数个数,答案对 109+7109+7 取模。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个整数 aiai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7109+7 取模。
数据范围
1≤n≤1001≤n≤100,
1≤ai≤2×1091≤ai≤2×109输入样例:
3 2 6 8
输出样例:
12
import java.util.*;
public class Main{
static int mod = (int) 1e9 + 7;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer,Integer> map = new HashMap<>();
while (n -- > 0) {
int x = sc.nextInt();
for (int i = 2; i <= x / i; i ++) {
while(x % i == 0) {
x /= i;
map.put(i,map.getOrDefault(i,0) + 1); //这里用到了一个map.getOrDefault的特殊方法,如果key为null的话取得值是后边填充的参数
}
}
if (x > 1) map.put(x,map.getOrDefault(x,0) + 1);
}
long res = 1;
for (int key:map.values()) {
res = res * (key + 1) % mod; //我们计算约数个数的公式
}
System.out.print(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)
while (b - - ) t = (t * a + 1) % mod;
给定 nn 个正整数 aiai,请你输出这些数的乘积的约数之和,答案对 109+7109+7 取模。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个整数 aiai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7109+7 取模。
数据范围
1≤n≤1001≤n≤100,
1≤ai≤2×1091≤ai≤2×109输入样例:
3 2 6 8
输出样例:
252
import java.util.*;
public class Main{
static int mod = (int) 1e9 + 7;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
HashMap<Integer,Integer> map = new HashMap<>();
int n = sc.nextInt();
while (n -- > 0) {
int x = sc.nextInt();
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()) {
int b = map.get(key);
long t = 1;
while (b -- > 0) {
t = (t * key + 1) % mod;
}
res = res * t % mod;
}
System.out.print(res);
}
}
四、最大公约数
//欧几里得算法,也可以叫做辗转相除法
/** | 这个符号表示整除
* 基本性质: d|a -> d|b -> d|a+b -> d|ax+by
* 核心原理:最大公约数 (a,b) = (b,a%b)
* 正证:d|a -> d|b
* a % b = a - (a / b) * b = a - c * b 由于d|ax+by 所以 d|a-c*b
* 反证:d|b -> d|a%b
* a % b = a - (a / b) * b = a - c * b = r
* 因为 d|b -> d|a - c * b
* 由于d|ax+by
* 则 d|a - c * b + c * b 就等于 d|a ,则反证成功
**/
给定 nn 对正整数 ai,biai,bi,请你求出每对数的最大公约数。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个整数对 ai,biai,bi。
输出格式
输出共 nn 行,每行输出一个整数对的最大公约数。
数据范围
1≤n≤1051≤n≤105,
1≤ai,bi≤2×1091≤ai,bi≤2×109输入样例:
2 3 6 4 6
输出样例:
3 2
import java.util.*;
public class Main {
public static int gcd (int a,int b) {
return b != 0 ? gcd(b,a % b) : a;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while (n -- > 0) {
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println(gcd(a,b));
}
}
}