标签:
两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。
第一行为一个数T,为数据组数。之后每组数据包含两行。
第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。
对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。
1 ≤ T ≤ 20
集合S内的数两两不同且范围在1到500000之间。
小数据
1 ≤ N ≤ 15
大数据
1 ≤ N ≤ 1000
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
按元素分解后质数个数分成2份,二分图匹配,
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXT (20+10) #define MAXn (1000+10) #define MAXN (2000+10) #define MAXM (10000000) #define MAXAi (500000+10) typedef long long ll; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} class Max_flow //dinic+当前弧优化 { public: int n,s,t; int q[MAXN]; int edge[MAXM],Next[MAXM],pre[MAXN],weight[MAXM],siz; void addedge(int u,int v,int w) { edge[++siz]=v; weight[siz]=w; Next[siz]=pre[u]; pre[u]=siz; } void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);} bool b[MAXN]; int d[MAXN]; bool SPFA(int s,int t) { For(i,n) d[i]=INF; MEM(b) d[q[1]=s]=0;b[s]=1; int head=1,tail=1; while (head<=tail) { int now=q[head++]; Forp(now) { int &v=edge[p]; if (weight[p]&&!b[v]) { d[v]=d[now]+1; b[v]=1,q[++tail]=v; } } } return b[t]; } int iter[MAXN]; int dfs(int x,int f) { if (x==t) return f; Forpiter(x) { int v=edge[p]; if (weight[p]&&d[x]<d[v]) { int nowflow=dfs(v,min(weight[p],f)); if (nowflow) { weight[p]-=nowflow; weight[p^1]+=nowflow; return nowflow; } } } return 0; } int max_flow(int s,int t) { int flow=0; while(SPFA(s,t)) { For(i,n) iter[i]=pre[i]; int f; while (f=dfs(s,INF)) flow+=f; } return flow; } void mem(int n,int s,int t) { (*this).n=n; (*this).t=t; (*this).s=s; siz=1; MEM(pre) } }S; int b[MAXAi]={0}; int p[MAXAi],tot=0; void make_prime(int n) { Fork(i,2,n) { if (!b[i]) p[++tot]=i; For(j,tot) { if (i*p[j]>n) break; b[i*p[j]]=b[i]+1; if (i%p[j]==0) break; } } } int n,a[MAXN]; int n1,n2; int a1[MAXN],a2[MAXN]; int main() { // freopen("erfentu.in","r",stdin); int T; cin>>T; make_prime(500000); b[1]=1; // For(i,100) cout<<i<<':'<<b[i]<<' '; For(kcase,T) { scanf("%d",&n); For(i,n) scanf("%d",&a[i]); sort(a+1,a+1+n); n1=0,n2=0; For(i,n) if (b[a[i]]%2) a1[++n1]=a[i]; else a2[++n2]=a[i]; int s=1,t=2+n; S.mem(2+n,1,2+n); For(i,n1) S.addedge2(s,i+1,1); For(i,n2) S.addedge2(1+n1+i,t,1); // For(i,n1) cout<<a1[i]<<' ';cout<<endl; // For(i,n2) cout<<a2[i]<<' ';cout<<endl; For(i,n1) For(j,n2) { int x=a1[i],y=a2[j]; if (x==1) { if (!b[y]) S.addedge(1+i,1+n1+j,1); } else { if ((x<y&&(y%x==0)&&!b[y/x]) || (y<x)&&(x%y==0)&&!b[x/y]) S.addedge2(1+i,1+n1+j,1); } } int ans=0; ans=n-S.max_flow(s,t); printf("Case #%d: %d\n",kcase,ans); } return 0; }
hiho 编程之美2015初赛第一场(质数相关-2分图匹配)
标签:
原文地址:http://blog.csdn.net/nike0good/article/details/45287659