Description
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 multipleof 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
感觉超棒的一道题,值得一做。。。挺巧妙的。。。
找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系。
思路:
最大独立集,必然是二分图。
最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建边,考虑到能这样建边的数一定是质因子个数奇偶不同,所以相当于按奇偶区分建立了二分图,然后求二分图最大匹配,得到最大独立集就行了。
#pragma comment(linker, "/STACK:102400000,102400000"
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define MAX 100005
#define INF 0x3f3f3f3f
#define LL long long
#define pii pair<int,int>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
///map<int,int>mmap;
///map<int,int >::iterator it;
using namespace std;
#define N 500010
#define M 40010
int a[M],b[N],num[M],factor[1000];
vector<int>mmap[M];
int n;
bool vis[M];
int linker[M];
bool dfs(int u)
{
for(int i=0;i<mmap[u].size();i++)
{
if(!vis[mmap[u][i]])
{
vis[mmap[u][i]]=true;
if(linker[ mmap[u][i] ]==-1||dfs(linker[ mmap[u][i] ]))
{
linker[mmap[u][i]]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int u;
int res=0;
for(u=1;u<=n;u++)
{
memset(vis,false,sizeof(vis));
if(dfs(u))
res++;
}
return res;
}
void init()
{
memset(num,0,sizeof(num));
memset(b,0,sizeof(b));
memset(linker,-1,sizeof(linker));
for(int i=1;i<=n;i++)
mmap[i].clear();
}
int main()
{
int T,Case,t;
scanf("%d",&T);
Case=1;
while(T--)
{
scanf("%d",&n);
init();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
b[ a[i] ]=i; ///对节点哈希
for(int i=1;i<=n;i++)
{
t = a[i];
int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积
for(int j=2;t>1&&j<=sqrt(t) ;j++)
if(t%j==0)
{
factor[cnt++] = j;
while(t%j==0)
t/=j,sum++;
}
if(t>1) //t有可能是质数
factor[cnt++]=t,sum++;
num[i] = sum;
for(int j=0;j<cnt;j++)
{
t = b[ a[i] / factor[j] ];
if(t==0) ///都是奇数或者偶数
continue;
if((sum&1)) ///是奇数 作为x部
mmap[i].push_back(t);
else ///是偶数
mmap[t].push_back(i);
}
}
printf("Case %d: %d\n",Case++,n-hungary());
}
return 0;
}
Hopcroft-Karp,数组有点乱。。。
#pragma comment(linker, "/STACK:102400000,102400000"
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define MAX 100005
#define INF 0x3f3f3f3f
#define LL long long
#define pii pair<int,int>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
///map<int,int>mmap;
///map<int,int >::iterator it;
using namespace std;
#define N 500010
#define M 40010
int a[N],b[N],num[N],factor[1000];
vector<int>mmap[M];
int um[N],vm[N],n;
int dx[M],dy[M],dis;
bool vis[M];
bool searchP()
{
queue<int>q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=1;i<=n;i++)
if(um[i]==-1)
{
q.push(i);
dx[i]=0;
}
while(!q.empty())
{
int u=q.front();q.pop();
if(dx[u]>dis) break;
for(int i=0;i<mmap[u].size();i++)
{
int v = mmap[u][i];
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(vm[v]==-1) dis=dy[v];
else
{
dx[vm[v]]=dy[v]+1;
q.push(vm[v]);
}
}
}
}
return dis!=INF;
}
bool dfs(int u)
{
for(int i=0;i<mmap[u].size();i++)
{
int v = mmap[u][i];
if(!vis[v]&&dy[v]==dx[u]+1)
{
vis[v]=1;
if(vm[v]!=-1&&dy[v]==dis) continue;
if(vm[v]==-1||dfs(vm[v]))
{
vm[v]=u;um[u]=v;
return 1;
}
}
}
return 0;
}
int maxMatch()
{
int res=0;
memset(um,-1,sizeof(um));
memset(vm,-1,sizeof(vm));
while(searchP())
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
if(um[i]==-1&&dfs(i))
res++;
}
return res;
}
void init()
{
memset(b,-1,sizeof(b));
memset(num,0,sizeof(num));
memset(vm,-1,sizeof(vm));
memset(um,-1,sizeof(um));
for(int i=0;i<=n;i++)
mmap[i].clear();
}
int main()
{
int k,kk,t,x,y,z;
scanf("%d",&k);
kk=0;
while(k--)
{
scanf("%d",&n);
init();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
b[ a[i] ]=i;
for(int i=1;i<=n;i++)
{
t = a[i];
int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积
for(int j=2;t>1&&j<=sqrt(t) ;j++)
if(t%j==0)
{
factor[cnt++] = j;
while(t%j==0)
t/=j,sum++;
}
if(t>1) //t有可能是质数
factor[cnt++]=t,sum++;
num[i] = sum;
for(int j=0;j<cnt;j++)
{
t = b[ a[i] / factor[j] ];
if( t==0 ) ///都是奇数或者偶数
continue;
if((sum&1)) ///是奇数 作为x部
mmap[i].push_back(t);
else ///是偶数
mmap[t].push_back(i);
}
}
printf("Case %d: %d\n",++kk,n-maxMatch());
}
return 0;
}
浙公网安备 33010602011771号