题目大意
在N(N <= 10000)个正整数里、找出gcd(p1, p2, p3, p4) == 1 的所有组合个数 pi <= 10000.
解题思路
- 求出<=10000的所有素数并保存
- 求出所有 m=p1 * p2 * p3 * p4 的数 (pi为素数且p1 < p2 < p3 < p4, m <= 10000)
- 根据容斥原理 ANS = C(N,4) - C(g2, 4) - C(g3,4) - ... - C(gp,4) + C(g23, 4) + C(g25, 4) + ... - C(g235, 4) - C(g237, 4) ....
其中g2表示N个数字里%2==0的个数,g23表示%(2 * 3)==0的个数,C(N,M)为组合数。
Example
需要测试数据的同学可以留言
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
new Main().start();
}
private long cn4(int n) {
if (n < 4)
return 0;
long ret = n;
ret *= (ret - 1) * (ret - 2) * (ret - 3);
return ret / 24;
}
int[] p = new int[2000];
int tp;
int[] odd = new int[10001];
private int find(int m) {
int ret = 0;
for (int i = 0; i < tp && m >= p[i] * p[i]; i++) {
if (m % p[i] == 0) {
m /= p[i];
if (m % p[i] == 0) {
return -1;
}
ret++;
}
}
if (m != 1) {
ret++;
}
return ret & 1;
}
private void start() {
Scanner in = new Scanner(System.in);
int n;
int[] a = new int[10000];
tp = 0;
p[tp++] = 2;
for (int i = 3; i < 10000; i += 2) {
if (isP(i)) {
p[tp++] = i;
}
}
for (int i = 2; i <= 10000; i++) {
odd[i] = find(i);
}
while (in.hasNextInt()) {
n = in.nextInt();
long ans = cn4(n);
int max = 0;
for (int i = 0; i < n; i++) {
a[i] = in.nextInt();
max = Math.max(a[i], max);
}
for (int i = 2; i * 4 <= max; i++) {
if (odd[i] == -1)
continue;
int s = 0;
for (int j = 0; j < n; j++) {
if (a[j] % i == 0) {
s++;
}
}
long tmp = cn4(s);
if (odd[i] == 1) {
ans -= tmp;
} else {
ans += tmp;
}
}
System.out.println(ans);
}
}
private boolean isP(int m) {
for (int i = 3; i * i <= m; i += 2) {
if (m % i == 0) {
return false;
}
}
return true;
}
}