Prime Independence
LightOJ - 1356A 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.
OutputFor each case, print the case number and the size of the largest prime independent subset.
Sample Input3
5
2 4 8 16 32
5
2 3 4 6 9
3
1 2 3
Sample OutputCase 1: 3
Case 2: 3
Case 3: 2
Note1. An integer is said to be a prime if it's divisible by exactly two distinct integers. First few prime numbers are 2, 3, 5, 7, 11, 13, ...
2. Dataset is huge, use faster I/O methods.
Restriction: If a % b == 0 && a / b = k where k is a prime number, then a and b cannot exist in a set at the same time.
The meaning of the question: give you n numbers, let you find the largest set that satisfies the above constraints, and output the number of elements.
Idea: Build a bipartite graph according to the parity of the number of prime factors of each number, and construct a good graph. Let's run HK, Hungary didn't dare to write, and even my HK didn't dare to use vector.
Mapping: It is not possible to traverse the mapping with a two-layer for loop, and the O(n*n) mapping complexity cannot be afforded. You can find all prime factors p[] of each number a[i], judge whether a[i] / p[] exists, and then build a map according to the parity. In this way, the worst time complexity of mapping is O(n*10), and then adding HK, the total time complexity
O(sqrt(n) * m + n * 10)。
code:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #define MAXN 40000+10 #define MAXM 1000000+10 #define INF 0x3f3f3f3f #define debug printf("1\n"); using namespace std; struct Edge{ int to, next; }; Edge edge[MAXM]; int head[MAXN], edgenum; int P[500010], num[500010];//Record whether each number is a prime number record the number of prime factors in each number int a[MAXN]; int id[MAXN]; int oddnum, evennum; void getP() { memset(P, 0, sizeof(P)); for(int i = 2; i <= 500000; i++) { if(P[i]) continue; for(int j = 2*i; j <= 500000; j+=i) P[j] = 1; } P[1] = 1; } //vector<int> p[500000+10]; void getPsum() { for(int j = 1; j <= 500000; j++) { int cnt = 0; int n = j; for(int i = 2; i * i <= n; i++) { if(n % i == 0) { while(n % i == 0) { cnt++; n /= i; } } } if(n > 1) cnt++; num[j] = cnt; } } void init(){ edge = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v) { Edge E1 = {v, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; } int n; int force[500010]; int p[30], top; void getprime(int n) { top = 0; for(int i = 2; i * i <= n; i++) { if(n % i == 0) { p[top++] = i; while(n % i == 0) n /= i; } } if(n > 1) p[top++] = n; } void getMap() { scanf("%d", &n); oddnum = evennum = 0; memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); vis[a[i]] = i;//Mark the element has appeared if(num[a[i]] & 1) id[i] = ++oddnum; else id[i] = ++evennum; } init(); for(int i = 1; i <= n; i++) { getprime(a[i]);//Process prime factor for(int j = 0; j < top; j++) { int goal = a[i] / p[j]; int index = vis[goal]; if(index)//exist { if(num[a[i]] & 1 && num[a[index]] % 2 == 0) addEdge(id[i], id[index]); else if(num[a[i]] % 2 == 0 && num[a[index]] & 1) addEdge(id[index], id[i]); } } } } bool used[MAXN]; int dx[MAXN], dy[MAXN]; int mx[MAXN], my[MAXN]; you are DFS (you are) { for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(!used[v] && dy[v] == dx[u] + 1) { used[v] = true; if(my[v] == -1 || DFS(my[v])) { my[v] = u; mx[u] = v; return 1; } } } return 0; } int kcase = 1; void HK() { memset(mx, -1, sizeof(mx)); memset(my, -1, sizeof(my)); int years = 0; while(1) { bool flag = false; memset(dx, 0, sizeof(dx)); memset(dy, 0, sizeof(dy)); queue<int> Q; for(int i = 1; i <= oddnum; i++) if(mx[i] == -1) Q.push(i); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(!dy[v]) { dy[v] = dx[u] + 1; if(my[v] == -1) flag = true; else { dx[my[v]] = dx[u] + 1; Q.push(my[v]); } } } } if(!flag) break; memset(used, false, sizeof(used)); for(int i = 1; i <= oddnum; i++) if(mx[i] == -1) ans += DFS(i); } printf("Case %d: %d\n", kcase++, n - ans); } intmain() { getP(); getPsum (); int t; scanf("%d", &t); while(t--) { getMap(); HK (); } return 0; }