# Prime Independence LightOJ - 1356（质因子分解+最大点独立集）

## Prime Independence

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.

Sample Input

3

5

2 4 8 16 32

5

2 3 4 6 9

3

1 2 3

Sample Output

Case 1: 3

Case 2: 3

Case 3: 2

Note

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.

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 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;
}
void addEdge(int u, int v)
{
Edge E1 = {v, head[u]};
edge[edgenum] = E1;
}
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)
else if(num[a[i]] % 2 == 0 && num[a[index]] & 1)
}
}
}
}
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;
}  

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120