题目大意:中文题。
算法思路:首先找出每个数的质因数的个数,因为如果a和b是质数相关的话,那他们两个的质数的个数肯定是一奇,一偶,因此我们可以根据这个性质,将这些数分成两个部分,转化二分图的最大独立集求解,这道题我已开始用求解质因数的模板,结果发现这个模板对于相同的质因数只算一个(在这里wa了好多回=- =),后来只好打素数表求解。。。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; #define MAXN 1005 #define MAXN2 5500000 int t,n,e,size1,size2; int a[MAXN],match[MAXN],head[MAXN],nextt[MAXN]; int s1[MAXN],s2[MAXN]; bool maps[MAXN][MAXN]; bool visited2[MAXN]; typedef struct Edge { int u,v,c; }; Edge edges[MAXN]; /** * 线性筛法求素数表 * 复杂度: O(n) */ int prime[MAXN2] = {0},num_prime = 0; bool isNotPrime[MAXN2] = {true, true}; void GetPrime_Init()//初始化调用 { for(int i = 2 ; i < MAXN2 ; i ++) { if(! isNotPrime[i]) prime[num_prime ++]=i; for(int j = 0 ; j < num_prime && i * prime[j] < MAXN2 ; j ++) { isNotPrime[i * prime[j]] = true; if( !(i % prime[j])) break; } } } bool isPrime(int x) { for(int i=2;i*i<=x;i++) { if(x%i==0) return false; } return true; } void addNode(int u,int v,int c) { edges[e].u=u; edges[e].v=v; edges[e].c=c; nextt[e]=head[u]; head[u]=e++; } int dfs(int p) { for(int i=head[p];i+1;i=nextt[i]){ int v=edges[i].v; if(visited2[v]) continue; visited2[v]=1; if(match[v]==-1||dfs(match[v])){ match[v]=p; return 1; } } return 0; } void solve_div(int kk) { int kk2=kk; int num=0; for(int i=0;prime[i]<=kk;i++) { while(kk%prime[i]==0) { num++; kk/=prime[i]; } } if(num%2!=0) { s1[size1++]=kk2; } else { s2[size2++]=kk2; } } int main() { GetPrime_Init(); scanf("%d",&t); int cnt=0; while(t--) { size1=0,size2=0,e=0; memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); memset(maps,false,sizeof(maps)); memset(match,-1,sizeof(match)); memset(head,-1,sizeof(head)); memset(nextt,-1,sizeof(nextt)); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { solve_div(a[i]); } for(int i=0;i<size1;i++) { for(int j=0;j<size2;j++) { if(s1[i]%s2[j]==0&&isPrime(s1[i]/s2[j])) { addNode(i,j,1); } else if(s2[j]%s1[i]==0&&isPrime(s2[j]/s1[i])) { addNode(i,j,1); } } } int sum=0; for(int i=0;i<size1;i++) { memset(visited2,false,sizeof(visited2)); sum+=dfs(i); } printf("Case #%d: %d\n",++cnt,n-sum); } return 0; }
在这里再记录一下那个只记录一次的求解质因数的模板。
/*void Solve(int nn,int k)//利用容斥原理求解质因数 { v[k].clear(); for(int i=2; i*i<=nn; i++) { if(nn%i==0) { v[k].push_back(i); while(nn%i==0) nn/=i; } } if(nn>1) v[k].push_back(nn); //这个不可以缺少 }*/