[2015编程之美] 第一场C
题目3 : 质数相关
时间限制:2000ms
单点时限:1000ms
内存限制:256MB
描述
两个数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
好像是LOJ的原题,- -
二分匹配求最大独立集。#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; #define INF 0x3f3f3f3f #define ll long long #define N 1010 #define M 500000 int n,m,k; int a[N]; int vis[N]; int match[N]; int mpt[N][N]; int tot; bool isprime[M+10]; int prime[M+10]; void init() { tot=0; memset(isprime,true,sizeof(isprime)); isprime[0]=isprime[1]=false; for(int i=2;i<=M;i++) { if(isprime[i]) prime[tot++]=i; for(int j=0;j<tot;j++) { if((ll)i*prime[j]>M) break; isprime[i*prime[j]]=false; if(i%prime[j]==0) break; } } } int dfs(int u) { for(int j=1;j<=n;j++) { if(!vis[j] && mpt[u][j]) { vis[j]=1; if(match[j]==-1 || dfs(match[j])) { match[j]=u; return 1; } } } return 0; } bool judge(int a,int b) { if(a>b) swap(a,b); if(b%a) return 0; int k=b/a; if(isprime[k]) return 1; return 0; } int main() { init(); int T,iCase=1; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(mpt,0,sizeof(mpt)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(judge(a[i],a[j])) { mpt[i][j]=1; mpt[j][i]=1; } } } printf("Case #%d: ",iCase++); int ans=0; memset(match,-1,sizeof(match)); for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",n-ans/2); } return 0; }
趁着还有梦想、将AC进行到底~~~by 452181625