https://atcoder.jp/contests/arc080/tasks/arc080_d
Problem Statement
There are infinitely many cards, numbered 1 1 1, 2 2 2, 3 3 3, . . . ... ... Initially, Cards x 1 x_1 x1, x 2 x_2 x2, . . . ... ..., x N x_N xN are face up, and the others are face down.
Snuke can perform the following operation repeatedly:
- Select a prime p p p greater than or equal to 3 3 3. Then, select p p p consecutive cards and flip all of them.
Snuke’s objective is to have all the cards face down. Find the minimum number of operations required to achieve the objective.
Constraints
- 1 ≤ N ≤ 100 1 ≤ N ≤ 100 1≤N≤100
- KaTeX parse error: Expected 'EOF', got '&' at position 9: 1 ≤ x_1 &̲lt; x_2 < ..…
Input
Input is given from Standard Input in the following format:
N
N
N
x
1
x_1
x1
x
2
x_2
x2
.
.
.
...
...
x
N
x_N
xN
Output
Print the minimum number of operations required to achieve the objective.
思路:异或差分,网络流
分三类讨论:
考虑消去 b i = b j = 1 ( i < j ) b_i=b_j=1(i<j) bi=bj=1(i<j),的代价。
2 ∤ ( j − i ) 2∤(j−i) 2∤(j−i) 且 j − i j−i j−i 为素数 显然我们只需要 1 次操作。
2 ∣ ( j − i ) 2∣(j−i) 2∣(j−i) 若 j − i = 2 j−i=2 j−i=2,我们可以翻转长度 5 和 3 的区间,其他情况根据歌德巴赫猜想我们只需要 2 次操作一定能够消去。
2 ∤ ( j − i ) 2∤(j−i) 2∤(j−i) 且 j − i j−i j−i 不为素数(注意包括 1) 与第二种情况同理,但由于我们只能用奇素数,我们需要 3 次操作才能消去。
#include<bits/stdc++.h>
using namespace std;
const int N = 1100, inf = 0x7fffffff;
struct edge {
int u, v, c, nxt;
};
int head[N], s, t, dep[N], cur[N];
vector<edge> e;
void init() {
// e.clear();
memset(head, -1, sizeof head);
}
void add(int u, int v, int c) {
e.push_back({u, v, c, head[u]});
head[u] = e.size() - 1;
e.push_back({v, u, 0, head[v]});
head[v] = e.size() - 1;
}
bool bfs() {
queue<int> q;
q.push(s);
memset(dep, -1, sizeof dep);
dep[s] = 1;
cur[s] = head[s];
while (q.size()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v, c = e[i].c;
if (dep[v] == -1 && c) {
dep[v] = dep[u] + 1;
cur[v] = head[v];
q.push(v);
}
}
}
return dep[t] != -1;
}
int dfs(int x, int lim) {
if (x == t)return lim;
int flow = 0;
for (int i = cur[x]; ~i; i = e[i].nxt) {
int y = e[i].v, c = e[i].c;
if (dep[y] == dep[x] + 1 && c) {
int nl = min(c, lim - flow);
if (!nl)dep[y] = -1;
int p = dfs(y, nl);
flow += p;
e[i].c -= p;
e[i ^ 1].c += p;
if (flow == lim)return lim;
}
}
return flow;
}
int dinic() {
int ans = 0;
while (bfs()) {
ans += dfs(s, inf);
}
return ans;
}
bool ok(int x) {
if (x <= 2) return false;
if (x % 2 == 0) return false;
for (long long i = 2; i * i <= x; i++) {
if (x % i == 0) {
return false;
}
}
return true;
}
int main() {
int n;
cin >> n;
map<int, int> a, b;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
a[x] = 1;
}
for (auto [x, y]: a) {
int ax = y;
int axd = a.count(x - 1);
int axp = a.count(x + 1);
b[x] = ax ^ axd;
b[x + 1] = axp ^ ax;
}
vector<int> dian;
for (auto [x, y]: b) {
if (y == 1) {
dian.push_back(x);
// cout << x << "#\n";
}
}
int dian_num = dian.size();
s = dian_num * 2 + 1, t = dian_num * 2 + 2;
init();
for (int i = 0; i < dian_num; i++) {
for (int j = i + 1; j < dian_num; j++) {
if (ok(dian[j] - dian[i])) {
if (dian[i] % 2 == 0) {
add(i, j, 1);
} else {
add(j, i, 1);
}
}
}
}
int ji = 0, ou = 0;
for (int i = 0; i < dian_num; i++) {
if (dian[i] % 2 == 0) {
add(s, i, 1);
ou++;
} else {
add(i, t, 1);
ji++;
}
}
int ans1 = dinic();
ou -= ans1;
ji -= ans1;
int ans2 = ou / 2 * 2 + ji / 2 * 2;
ou %= 2;
ji %= 2;
cout << ans1 + ans2 + 3 * (ou || ji);
return 0;
}