时间复杂度O(n)
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Scanner;
public class Main {
static int N = 1000010;
static int n;
static Scanner s = new Scanner(System.in);
public static void main(String[] args) {
n = s.nextInt();
while (n-- != 0) {
int t = s.nextInt();
primesFactor(t);
}
}
static void primesFactor(int t) {
LinkedHashMap<Integer , Integer> primes = new LinkedHashMap<>();
for (int i = 2; i <= t / i; i++)
while (t % i == 0) {
t /= i;
set( i , primes);
}
if (t > 1)
set(t , primes);
for (Integer key : primes.keySet())
System.out.println(key + " " + primes.get(key));
System.out.println();
}
public static void set(int i , HashMap<Integer , Integer> primes){
int p = primes.get(i) == null ? 0 : primes.get(i);
primes.put(i , p + 1);
}
}
拿Java写算法一个字难受!
但是有些题还是能拿捏的 , 尽力就好!
说正事 , 我们如何理解这题并求出分解出质因数以及对应次方的;
首先我们需要了解一个数论里面的公式 N = P^a1 * P^a2 * P^a3 ………… * P^an;
这个公式的意思就是 任何一个合数都可以分解成
质数的指数乘积的形式;
由此我们可以知道 找到一个数的质因数只需要找到将这个数进行拆解成以上形式即可;
我们这里都是对合数进行分解质因数 , 质数的质因数就是它自己 和 1;
for (int i = 2; i <= t / i; i++)
while (t % i == 0) {
t /= i;
set( i , primes);
}
这段代码是我们需要好好分析的 , 从 2开始枚举 , 枚举到 sqrt(t);
我们用较小的质因数去除这个数 ,如果能整除那么整除这个数一定是质数!
为什么一定是质数呢?
因为我们枚举 2 的时候 如果能被 2整除 , 2 是质数
然后将这个数不断取模看看能否整除 , 可以就整除;
我们可以发现 , 这个数此时去除了所有能与2 整除的因数
比如 4 肯定跟剩下的这个商肯定不能整除了;
以此类比3 , 5 , 6 , ……到 我们需要拆分这个数之间所有的
能与2 、3 、5整除的数都被整除除掉了, 变成了 质数 和指数
的形式。
所以我们确定 t % i == 0 这个条件成立 t 一定是质数!
为什么我们除的范围 是 2 到 sqrt( t )呢?
首先 1 是所有数的质因数 , 不需要考虑
而且如果从 1 开始 while会死循环
1 和任何数都能整除!
其次为什么不需要除到 t ;
因为我用较小的质因数除剩下的如果大于 sqrt(t)
那么我们就可以做一个单独判断一下加入到集合中即可
为什么需要单独判断大于 1 呢 , 因为 1 作为约数
而且有个细节忘记了 1 不是质数!不是质数! 不是质数!
最后就是学Java的小伙伴 , 记得用LinkedHashMap因为
数组开太大内存会爆 , 开小了 , 无法映射到所有的值;
为什么一定用 LinkedHashMapn呢 因为ArrayList也是数组
会下标越界 , 其次就是 不能用 HashMap 因为不能有序取出
它会hash到相对随机(其实是由规律的)位置,不能按存储顺序
取出 , 所以我们要用LinkedHahsMap
因为它维护hash表 还维护了 双向链表 可以按存储顺序取出
所以 用它!用它 !用它!