版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/86538186
【思路要点】
- 考虑删去最少的数使得异或和为 ,显然,我们不会删去两个相同的数,可以用最短路求解,记 表示使删除的数异或和为 的最少步数。
- 注意到 ,可以用 优化转移。
- 时间复杂度 。
- 笔者训练当时选择了一个复杂度没有保证(或者说我不会证明的做法),即双向 ,时间复杂度未知,但笔者自己不会构造让其超时的数据。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 524288; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, a[MAXN], dist[MAXN]; bool exist[MAXN]; int main() { freopen("sub.in", "r", stdin); freopen("sub.out", "w", stdout); read(n); int goal = 0; for (int i = 1; i <= n; i++) { int x; read(x); goal ^= x; if (!exist[x]) { exist[x] = true; a[++m] = x; } } for (int i = 1; i < MAXN; i++) dist[i] = -1; dist[0] = 0; if (goal == 0) { writeln(n); return 0; } static int q[MAXN]; int l = 0, r = 0; dist[0] = 0; while (l <= r) { if (l == 0 || dist[q[l]] != dist[q[l - 1]]) { int pos = l; while (pos <= r && dist[q[pos]] == dist[q[l]]) { int res = q[pos++]; if (dist[res ^ goal] != -1) { writeln(n - dist[res] - dist[res ^ goal]); return 0; } } } int tmp = q[l++]; for (int i = 1; i <= m; i++) { int res = tmp ^ a[i]; if (dist[res] == -1) { dist[res] = dist[tmp] + 1; if (dist[res ^ goal] != -1 && dist[res ^ goal] < dist[res]) { writeln(n - dist[res] - dist[res ^ goal]); return 0; } q[++r] = res; } } } assert(false); return 0; }