P9575 「TAOI-2」喵了个喵 后面忘了是几
定义序列 $b_i=\gcd(a_i,x)$。
当 $n$ 为偶数,直接 $x=1$ 即可。所以我们只考虑 $n$ 为奇数。考虑 $x=2$,序列就变成 一堆 $1$ 一堆 $2$。
如果和为偶数,枚举 $2$ 的个数,相应地找到 $1$ 的个数即可(找不到的话怎么办呢?大家先思考一下)。
如果和为奇数,我们可以证明无解:
若取 $x$ 偶数,原来的 $1$ 还是 $1$,原来的 $2$ 会变但是依然为偶数,奇偶性不变,仍无解;若取 $x$ 奇数,原序列全是奇数,而 $n$ 为奇数,奇数个奇数相加仍为奇数,无解。
看起来到这里就差不多了,然而我们会碰到找不到的情况。例如:
3
2 2 4
此时 $b=\{2,2,2\}$,我们想将其分为 $3+3$,但是找不到 $1$ 啊!
所以上面做法的正确性成立当且仅当 $b$ 中存在 $1$。
那怎么办呢。我们不妨在二进制下看一些数。它们有一些共同的 $0$ 后缀(也有可能没有,即长度为 $0$)。我们将后面公共的 $0$ 全部遮住不看,从第一个存在 $1$ 的位考虑。这里再取 $x=2$ 是显然有 $1$ 存在的。注意到后面公共 $0$ 表示的数即为 $\min(\operatorname{lowbit}(a_i))$,于是我们构造 $x=2\min(\operatorname{lowbit}(a_i))$,对 $\dfrac{a_i}{\min(\operatorname{lowbit}(a_i))}$ 做最简单的 $x=2$ 考虑即可。其原理是 $c\gcd(a,b)=\gcd(ac,ab)$。
赛时比较脑弹写了 set 维护位置,根本不用,凭空多一个 log。用其他东西随便做。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 10;
int n;
int a[maxn];
bool b[maxn];
set<int> s[2];
int g = 1e10;
signed main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i], g = min(g, a[i] & -a[i]);
for (int i = 1; i <= n; i++) a[i] /= g;
if (!(n & 1)) {
cout << 1 << endl;
for (int i = 1; i <= n; i++) cout << (i <= (n >> 1));
} else {
for (int i = 1; i <= n; i++) s[a[i] & 1].insert(i);
if (s[1].size() & 1) puts("-1");
else {
cout << g * 2 << endl;
int tot = s[1].size() / 2 + s[0].size();
for (int i = 0; i <= s[0].size(); i++) {
if (tot - i * 2 >= 0 && tot - i * 2 <= s[1].size()) {
for (int j = 1; j <= i; j++) {
b[*s[0].begin()] = 1;
s[0].erase(*s[0].begin());
}
for (int j = 1; j <= tot - i * 2; j++) {
b[*s[1].begin()] = 1;
s[1].erase(*s[1].begin());
}
for (int i = 1; i <= n; i++) cout << b[i];
return 0;
}
}
}
}
return 0;
}