题意:
给你一个集合,让你从这个集合中挑选出几个数,使得这几个数中任意两个数相除后的值不能为素数
即挑选出来的这几个数不能互相冲突
最大独立集 = 所有点数 - 最大匹配数
呵。。呵。。。原先用的二维数组来标记 呵。。呵。。。。呵。。呵。。ER。。。MLE
vector 大法好! orz
mmp。。。。。呸。。。吐槽完毕。。。。
因为a = b * k (k为质数) 所以a必然比b多一个质因子 所以把偶数个质因子的数放到左边 把奇数个质因子的数放到右边
代码如下:
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define MOD 2018 #define LL long long #define ULL unsigned long long #define maxn 500010 #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int LL_INF = 0x7fffffffffffffff,INF = 0x3f3f3f3f; int dx[maxn], dy[maxn], cx[maxn], cy[maxn], used[maxn]; int dot[maxn], vis[maxn], primes[maxn]; int nx, ny, dis, n, m; int B[maxn], goal[maxn]; vector<int> G[40005]; void init() { int cnt = 0; mem(vis,0); for(int i=2; i<maxn; i++) if(!vis[i]){ primes[cnt++] = i; for(LL j=(LL)i*i; j<maxn; j+=i) vis[j] = 1; } } int bfs() { queue<int> Q; dis = INF; mem(dx,-1); mem(dy,-1); for(int i=1; i<=nx; i++) { if(cx[i] == -1) { Q.push(i); dx[i] = 0; } } while(!Q.empty()) { int u = Q.front(); Q.pop(); if(dx[u] > dis) break; for(int v=0; v<G[u].size(); v++) { int i = G[u][v]; if(dy[i] == -1) { dy[i] = dx[u] + 1; if(cy[i] == -1) dis = dy[i]; else { dx[cy[i]] = dy[i] + 1; Q.push(cy[i]); } } } } return dis != INF; } int dfs(int u) { for(int v=0; v<G[u].size(); v++) { int i = G[u][v]; if(!used[i] && dy[i] == dx[u] + 1) { used[i] = 1; if(cy[i] != -1 && dis == dy[i]) continue; if(cy[i] == -1 || dfs(cy[i])) { cy[i] = u; cx[u] = i; return 1; } } } return 0; } int hc() { int res = 0; mem(cx,-1); mem(cy,-1); while(bfs()) { // cout<<22222222222<<endl; mem(used,0); for(int i=1; i<=nx; i++) { if(cx[i] == -1 && dfs(i)) res++; } } return res; } int main() { init(); int T; int ans = 0; scanf("%d",&T); while(T--) { for(int i=0; i<40005; i++) G[i].clear(); mem(goal,-1); scanf("%d",&n); for(int i=1; i<=n; i++){ scanf("%d",&dot[i]); } sort(dot+1,dot+n+1); for(int i=1; i<=n; i++) goal[dot[i]] = i; for(int i=1; i<=n; i++) { int cnt = 0, cnt2 = 0; int t = dot[i]; for(int j=0; primes[j] * primes[j] <= t; j++) if(t % primes[j] == 0) { B[cnt++] = primes[j]; while(t % primes[j] == 0) { t /= primes[j]; cnt2++; } } if(t > 1) B[cnt++] = t, cnt2++; for(int j=0; j<cnt; j++) { t = goal[dot[i]/B[j]]; if(t <= i && t != -1) { if(cnt2 & 1) G[i].push_back(t); else G[t].push_back(i); } } } nx = n, ny = n; printf("Case %d: %d\n",++ans,n - hc()); } return 0; }