1356 - Prime Independence
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
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 |
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 |
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.
题目大意:给你一个集合,问最大的子集满足集合内任意两个数都不能通过乘素数得到。
最大独立集=点数-匹配数
这道题卡匈牙利,只能用HK写,算是存个模板吧
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define debug cout<<"test"<<endl
const int maxn=4e4+7;
const int maxm=1e6+107;
const int inf=0x3f3f3f3f;
struct Node
{
int to;
int next;
}edge[maxm];
int cnt;
int odd,even;
int id[500010];
int num[maxn];
int head[maxn];
bool prime[500010];
int prime_cnt[500010];
bool vis[500010];
int match[500010];
int vis_index[500010];
void init()
{
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
memset(vis_index,0,sizeof(vis_index));
cnt=0;
odd=even=0;
return;
}
void add(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
return;
}
void init_prime()
{
memset(prime,false,sizeof(prime));
prime[1]=true;
for(int i=2;i<=500000;i++)
{
if(prime[i]==false)
{
for(int j=i+i;j<=500000;j+=i)
{
prime[j]=true;
}
}
}
return;
}
void getPrimeSum()
{
for(int i=1;i<=500000;i++)
{
int num_cnt=0;
int x=i;
for(int j=2;j*j<=i;j++)
{
if(x%j==0)
{
while(x%j==0)
{
num_cnt++;
x/=j;
}
}
}
if(x>1)
{
num_cnt++;
}
prime_cnt[i]=num_cnt;
}
return;
}
int uN;
int Mx[maxn],My[maxn];
int dx[maxn],dy[maxn];
int dis;
bool used[maxn];
bool dfs(int node)
{
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(!used[v]&&dy[v]==dx[node]+1)
{
used[v]=true;
if(My[v]!=-1&&dy[v]==dis)
{
continue;
}
if(My[v]==-1||dfs(My[v]))
{
My[v]=node;
Mx[node]=v;
return true;
}
}
}
return false;
}
bool searchP()
{
queue<int> que;
dis=inf;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=1;i<=uN;i++)
{
if(Mx[i]==-1)
{
que.push(i);
dx[i]=0;
}
}
while(!que.empty())
{
int node=que.front();
que.pop();
if(dx[node]>dis) break;
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(dy[v]==-1)
{
dy[v]=dx[node]+1;
if(My[v]==-1)
{
dis=dy[v];
}
else
{
dx[My[v]]=dy[v]+1;
que.push(My[v]);
}
}
}
}
return dis!=inf;
}
int HK()
{
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP())
{
memset(used,false,sizeof(used));
for(int i=1;i<=uN;i++)
{
if(Mx[i]==-1&&dfs(i))
{
res++;
}
}
}
return res;
}
int top;
int p[110];
void ldj(int x)
{
top=0;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
p[top++]=i;
while(x%i==0)
{
x/=i;
}
}
}
if(x>1)
{
p[top++]=x;
}
return;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
init_prime();
getPrimeSum();
int test;
scanf("%d",&test);
for(int cas=1;cas<=test;cas++)
{
init();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
int x=prime_cnt[num[i]];
vis_index[num[i]]=i;
if(x&1)
{
id[i]=++odd;
}
else
{
id[i]=++even;
}
}
for(int i=1;i<=n;i++)
{
ldj(num[i]);
for(int j=0;j<top;j++)
{
int x=num[i]/p[j];
int ind=vis_index[x];
if(ind)
{
if(prime_cnt[num[i]]&1&&prime_cnt[num[ind]]%2==0)
{
add(id[i],id[ind]);
}
else if(prime_cnt[num[i]]%2==0&&prime_cnt[num[ind]]&1)
{
add(id[ind],id[i]);
}
}
}
}
uN=odd;
printf("Case %d: %d\n",cas,n-HK());
}
return 0;
}