A set of integers is called prime independent if none of its member is a prime multiple of another member. An integer a is said to be a prime multiple of b if,
a = b x k (where k is a prime [1])
So, 6 is a prime multiple of 2, but 8 is not. And for example, {2, 8, 17} is prime independent but {2, 8, 16} or {3, 6} are not.
Now, given a set of distinct positive integers, calculate the largest prime independent subset.
Input
Input starts with an integer T (≤ 20), denoting the number of test cases.
Each case starts with an integer N (1 ≤ N ≤ 40000) denoting the size of the set. Next line contains N integers separated by a single space. Each of these N integers are distinct and between 1 and 500000 inclusive.
Output
For each case, print the case number and the size of the largest prime independent subset.
usingnamespacestd; #define ms(a, b) memset((a), (b), sizeof(a))
typedeflonglong ll; typedefunsignedlonglong ull; typedef pair<int, int> P; constint N = 4e4 + 5; constint M = 5e5 + 5; constint INF = 0x3f3f3f3f; const ll ll_max = 4557430888798830399; inlineintread(){ int res = 0;bool f = 0;char ch = getchar(); while (ch < '0' || ch > '9') {if (ch == '-') f = 1;ch = getchar();} while (ch <= '9' && ch >= '0') {res = (res << 3) + (res << 1) + ch - '0';ch = getchar();} return f ? (~ res + 1) : res; } int vis[N]; int match[N]; vector<int>fac[N]; int pos[M]; int cnt[N]; structedge { int u, v, ne; } ed[M];
int head[M], cnt1; int a[N], n; int pri[M]; bool is[M]; int num = 0;
voidis_pri(int n){ ms(is, true); is[1] = is[0] = false; for (int i = 2; i <= n; ++i){ if (is[i]) pri[++num] = i; for (int j = 1; j <= num && i * pri[j] <= n; ++j){ is[i * pri[j]] = false; if (i % pri[j] == 0) break; } } }
inlinevoidadd(int u, int v){ ed[cnt1] = {u, v, head[u]}; head[u] = cnt1++; }
inttofind(int u, int sgn){ // 二分图匹配 for (int i = head[u]; ~i; i = ed[i].ne) { int v = ed[i].v; // if (match[u]) continue; if (vis[v] != sgn) { vis[v] = sgn; if (!match[v] || tofind(match[v], sgn)) { match[v] = u; // match[u] = v; return1; } }
} return0; }
intmain(){ int t; is_pri(500000); // cout << num << "\n"; t = read(); for (int tt = 1; tt <= t; ++tt) { n = read(); ms(head, -1); for (int i = 1; i <= n; ++i) { int tmp; tmp = a[i] = read(); // ↓ 分解质因数 pos[tmp] = i; for (int p = 1; p <= num && pri[p] * pri[p] <= tmp; ++p) { if (tmp % pri[p] == 0) { fac[i].push_back(pri[p]); while(tmp % pri[p] == 0) tmp /= pri[p], ++cnt[i]; } } if (tmp > 1) fac[i].push_back(tmp), ++cnt[i]; }
for (int i = 1; i <= n; ++i) { int L = fac[i].size(); for (int j = 0; j < L; ++j) { int k = pos[a[i] / fac[i][j]]; // 如果存在这个数的话 if (k) { if (cnt[i] & 1) add(i, k); // 如果i的质因子的个数是奇数个 else add(k, i); // 否则k的质因子个数为奇数个 } }
} int ans = 0; for (int i = 1; i <= n; ++i) { if (tofind(i, i)) ans += 1; } printf("Case %d: %d\n", tt, n - ans); for (int i = 1; i <= n; ++i) { pos[a[i]] = 0; vis[i] = cnt[i] = pos[i] = match[i] = cnt1 = 0; fac[i].clear();