
正文
[BZOJ 4857][Jsoi2016]反质数序列
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
传送门
$ \color{green} {solution : } $
因为 $ 1 $ 的个数我们最多只能选一个,所以剩下的数如果组成素数那么只有一奇一偶,显然是个二分图模型
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010, inf = 0x3f3f3f3f;
int head[maxn], to[maxn << 1], v[maxn << 1], pos[maxn << 1], p;
inline void build(int a, int b, int c) {
v[++ p] = b; to[p] = head[a]; head[a] = p; pos[p] = c;
}
int dis[maxn], cur[maxn], s, t;
queue<int> tp;
bool bfs() {
memset(dis, 0, sizeof(dis)); dis[s] = 1; tp.push(s);
while ( !tp.empty()) {
int u = tp.front(); tp.pop();
for ( int i = head[u]; ~i; i = to[i])
if( !dis[v[i]] && pos[i])
dis[v[i]] = dis[u] + 1, tp.push(v[i]);
}
for ( int i = s; i <= t; ++ i) cur[i] = head[i];
return dis[t] != 0;
}
int dfs(int u, int f) {
if( !f || u == t) return f;
int flow = 0;
for ( int &i = cur[u]; ~i; i = to[i])
if( dis[v[i]] == dis[u] + 1){
int k = dfs(v[i], min(f, pos[i]));
if( k) {
pos[i] -= k; pos[i ^ 1] += k;
flow += k; f -= k;
if( !f) return flow;
}
}
return flow;
}
int max_flow() {
int ret = 0;
while ( bfs()) ret += dfs(s, inf);
return ret;
}
int prim[maxn], book[maxn], vl[maxn], cnt[maxn], tot, n;
int main() {
#ifndef ONLINE_JUDGE
freopen("2.in", "r", stdin);
#endif
memset(head, -1, sizeof(head)); p = -1;
scanf("%d", &n);
for ( int i = 1; i <= n; ++ i) scanf("%d", vl + i);
sort(vl + 1, vl + 1 + n);
int op = 1;
for ( int i = 1; i <= n; ++ i) {
if( vl[i] != vl[op]) vl[++ op] = vl[i];
++ cnt[op];
}
n = op; if( vl[1] == 1) cnt[1] = 1;
s = 0; t = n + 1;
for ( int i = 2; i <= (vl[n] << 1); ++ i) {
if( !book[i]) prim[++ tot] = i;
for ( int k = 1; k <= tot; ++ k) {
if( i * prim[k] > (vl[n] << 1)) break;
book[i * prim[k]] = 1;
if( i % prim[k] == 0) break;
}
}
int ret = 0;
for ( int i = 1; i <= n; ++ i) {
ret += cnt[i];
if( vl[i]&1) {
build(s, i, cnt[i]), build(i, s, 0);
for ( int k = 1; k <= n; ++ k) if( !book[vl[i]+vl[k]])
build(i, k, inf), build(k, i, 0);
}
else build(i, t, cnt[i]), build(t, i, 0);
}
printf("%d\n", ret - max_flow());
return 0;
}







