PDF (English) | Statistics | Forum |
Time Limit: 3 second(s) | Memory Limit: 32 MB |
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 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 Nintegers are distinct and between 1 and 500000 inclusive.
For each case, print the case number and the size of the largest prime independent subset.
Sample Input |
Output for Sample Input |
3 5 2 4 8 16 32 5 2 3 4 6 9 3 1 2 3 |
Case 1: 3 Case 2: 3 Case 3: 2 |
1. 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.
TLE到死啊,o(╯□╰)o O(n*n)的建图时间复杂度伤不起。。。
限制:若a % b == 0 && a / b = k其中k是质数,则a和b不能同时存在于一个集合。
题意:给你n个数,让你求出满足上面限制的最大集合,输出元素个数。
思路:根据每个数质因子个数的奇偶性建立二分图,构好图。跑HK吧,匈牙利没敢写,甚至我HK都没敢用vector。
建图:不能二层for循环遍历建图,O(n*n)的建图复杂度承受不起。可以求出每个数a[i]的所有质因子p[],判断a[i] / p[]是否存在,然后根据奇偶性建图。这样建图时间复杂度最坏也就是O(n*10),然后加上HK,总时间复杂度
O(sqrt(n) * m + n * 10)。
注意:不能直接预处理所有数的质因子,MLE o(╯□╰)o
AC代码:
#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];//记录每个数是否是质数 记录每个数里面质因子的个数 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(){ edgenum = 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 vis[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;//标记该元素 已经出现过 if(num[a[i]] & 1) id[i] = ++oddnum; else id[i] = ++evennum; } init(); for(int i = 1; i <= n; i++) { getprime(a[i]);//处理质因子 for(int j = 0; j < top; j++) { int goal = a[i] / p[j]; int index = vis[goal]; if(index)//存在 { 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]; int DFS(int u) { 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 ans = 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); } int main() { getP(); getPsum(); int t; scanf("%d", &t); while(t--) { getMap(); HK(); } return 0; }