You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
2.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<Long> primes(long num) {
ArrayList<Long> 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<Long, Long> 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("测试结束");
}
}