package class_2022_04_2_week; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; // 来自携程 // 给出n个数字,你可以任选其中一些数字相乘,相乘之后得到的新数字x // x的价值是x的不同质因子的数量 // 返回所有选择数字的方案中,得到的x的价值之和 public class Code01_SumOfValuesAboutPrimes { // 工具! // 返回num质数因子列表(去重) // 时间复杂度,根号(num) public static ArrayList primes(long num) { ArrayList ans = new ArrayList<>(); for (long i = 2; i * i <= num && num > 1; i++) { if (num % i == 0) { ans.add(i); while (num % i == 0) { num /= i; } } } if (num != 1) { ans.add(num); } return ans; } public static long sumOfValues1(int[] arr) { return process1(arr, 0, 1); } public static long process1(int[] arr, int index, long pre) { if (index == arr.length) { return (long) primes(pre).size(); } long p1 = process1(arr, index + 1, pre); long p2 = process1(arr, index + 1, pre * (long) arr[index]); return p1 + p2; } public static long sumOfValues2(int[] arr) { // key : 某个质数因子 // value : 有多少个数含有这个因子 HashMap cntMap = new HashMap<>(); for (int num : arr) { for (long factor : primes(num)) { cntMap.put(factor, cntMap.getOrDefault(factor, 0L) + 1L); } } int n = arr.length; long ans = 0; // count :含有这个因子的数,有多少个 // others : 不含有这个因子的数,有多少个 for (long count : cntMap.values()) { long others = n - count; ans += (power(2, count) - 1) * power(2, others); } return ans; } public static long power(long num, long n) { if (n == 0L) { return 1L; } long ans = 1L; while (n > 0) { if ((n & 1) != 0) { ans *= num; } num *= num; n >>= 1; } return ans; } // 为了测试 public static int[] randomArray(int len, int value) { int[] arr = new int[len]; for (int i = 0; i < len; i++) { arr[i] = (int) (Math.random() * value) + 1; } return arr; } // 为了测试 public static void main(String[] args) { int n = 10; int v = 20; int testTime = 5000; System.out.println("测试开始"); for (int i = 0; i < testTime; i++) { int[] arr = randomArray(n, v); long ans1 = sumOfValues1(arr); long ans2 = sumOfValues2(arr); if (ans1 != ans2) { System.out.println("出错了!"); BigInteger all = new BigInteger("1"); for (int num : arr) { all = all.multiply(new BigInteger(String.valueOf(num))); } System.out.println("所有数都乘起来 : " + all.toString()); System.out.println("长整型最大范围 : " + Long.MAX_VALUE); System.out.println("可以看看上面的打印,看看是不是因为溢出了"); break; } } System.out.println("测试结束"); } }