\quad 给 n n n 个数, A A A 被称为 B B B 的素倍数当前仅当 A = B × P A = B \times P A=B×P( P P P 为素数)
\quad 定义最大独立集为最多能选出多少个数,使得选出的数两两之间不存在素倍数关系.
\quad 求最大独立集.
\quad 1 ≤ N ≤ 1 0 4 , 1 ≤ e ≤ 5 × 1 0 5 1 \leq N \leq 10^4, 1 \leq e \leq 5 \times 10^5 1≤N≤104,1≤e≤5×105 且 e e e 两两不同.
\quad 图论、数论两开花ヾ(✿゚▽゚)ノ
#include
using namespace std;
namespace Graph
{
const int M = (int)8e4;
const int N = (int)1e5;
const int inf = 0x3f3f3f3f;
int n, m, S, T, cnt;
int head[M + 5];
struct node
{
int v, w, nx;
}Edge[N * 2 + 5];
int d[M + 5];
int cur[M + 5];
int q[M + 5], l, r;
void init()
{
cnt = 0;
for(int i = 0; i <= n; ++i)
{
head[i] = -1;
}
}
void add(int u, int v, int w)
{
Edge[cnt].v = v;
Edge[cnt].w = w;
Edge[cnt].nx = head[u];
head[u] = cnt++;
}
bool bfs()
{
l = 1, r = 0;
for(int i = 1; i <= n; ++i) d[i] = -1;
q[++r] = S, d[S] = 0, cur[S] = head[S];
while(l <= r)
{
int u = q[l++];
if(u == T) return 1;
for(int i = head[u]; ~i; i = Edge[i].nx)
{
int v = Edge[i].v;
if(d[v] == -1 && Edge[i].w)
{
d[v] = d[u] + 1;
cur[v] = head[v];
q[++r] = v;
}
}
}
return 0;
}
int dfs(int u, int limit)
{
if(u == T) return limit;
int flow = 0;
for(int i = cur[u]; ~i && flow < limit; i = Edge[i].nx)
{
cur[u] = i;
int v = Edge[i].v;
if(d[v] == d[u] + 1 && Edge[i].w)
{
int t = dfs(v, min(Edge[i].w, limit - flow));
if(!t) d[v] = -1;
Edge[i].w -= t, Edge[i^1].w += t, flow += t;
}
}
return flow;
}
int Dinic()
{
int r = 0, flow;
while(bfs()) while(flow = dfs(S, inf)) r += flow;
return r;
}
};
namespace Math
{
const int M = (int)5e5;
bool is_prime[M + 5];
int prime[M + 5], cnt;
int v[M + 5];//最小质因子
void init()
{
memset(is_prime, 1, sizeof(is_prime));
is_prime[0] = is_prime[1] = 0;
for(int i = 2; i <= M; ++i)
{
if(is_prime[i])
{
prime[++cnt] = i;
v[i] = i;
}
for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
{
is_prime[i * prime[j]] = 0;
v[i * prime[j]] = prime[j];
if(i % prime[j] == 0)
{
break;
}
}
}
}
};
typedef long long ll;
const int M = (int)4e4;
const int N = (int)4e4;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
const double eps = 1e-9;
int n, a[M + 5];
int n1, l[M + 5];
int n2, r[M + 5];
int fac[M + 5][10];
int len[M + 5];
int cal(int p)
{
len[p] = 0;
int x = a[p], c = 0;
while(x > 1)
{
fac[p][++len[p]] = Math::v[x];
x /= Math::v[x];
++c;
}
sort(fac[p] + 1, fac[p] + len[p] + 1);
len[p] = unique(fac[p] + 1, fac[p] + len[p] + 1) - (fac[p] + 1);
return c;
}
int bsl(int x)
{
int L = 1, R = n1 + 1, mid;
while(L < R)
{
mid = (L + R) >> 1;
if(a[l[mid]] >= x) R = mid;
else L = mid + 1;
}
return R;
}
int bsr(int x)
{
int L = 1, R = n2 + 1, mid;
while(L < R)
{
mid = (L + R) >> 1;
if(a[r[mid]] >= x) R = mid;
else L = mid + 1;
}
return R;
}
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
Math::init();
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
scanf("%d", &n); n1 = n2 = 0;
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
for(int i = 1, c; i <= n; ++i)
{
c = cal(i);
if(c & 1) l[++n1] = i;
else r[++n2] = i;
}
Graph::n = n1 + n2 + 1; Graph::init();
for(int i = 1, x, y, p; i <= n1; ++i)
{
Graph::add(0, i, 1), Graph::add(i, 0, 0);
for(int j = 1; j <= len[l[i]]; ++j)
{
y = a[l[i]] / fac[l[i]][j];
p = bsr(y);
if(p <= n2 && a[r[p]] == y) Graph::add(i, n1 + p, 1), Graph::add(n1 + p, i, 0);
}
}
for(int i = 1, x, y, p; i <= n2; ++i)
{
Graph::add(n1 + i, n1 + n2 + 1, 1), Graph::add(n1 + n2 + 1, n1 + i, 0);
for(int j = 1; j <= len[r[i]]; ++j)
{
y = a[r[i]] / fac[r[i]][j];
p = bsl(y);
if(p <= n1 && a[l[p]] == y) Graph::add(p, n1 + i, 1), Graph::add(n1 + i, p, 0);
}
}
Graph::S = 0, Graph::T = n1 + n2 + 1;
printf("Case %d: %d\n", ca, n1 + n2 - Graph::Dinic());
}
return 0;
}