思路
若原数组已经无法划分,则答案为零,可通过 $01$ 背包检验。若原数组可以被划分,则所有元素的和 $s$ 一定是偶数。如果此时数组里存在一个奇数元素,去掉它,元素之和就会变成奇数,此时数组一定无法再被划分。若数组的所有元素都是偶数,则对这些元素不断除二,直到出现一个奇数,将它删掉,此时的数组就不可以再被划分。
证明:若不断除二后第一次出现奇数时,将它去掉得到的数组 $A$ 不可划分,则原数组去掉相同位置的元素得到的数组 $B$ 也不可划分。首先,将 $B$ 中元素同时不断除二,若干次后一定会得到 $A$ 中所有元素。反之 $A$ 中所有元素同时不断乘二,若干次后一定会得到 $B$ 中所有元素,即 $A, B$ 元素一一对应。其次,假设 $B$ 可被划分成 $C, D$,由于 $A, B$ 一一对应,因此 $B$ 的两个子序列 $C, D$ 一定分别与 $A$ 的某两个子序列 $E, F$ 一一对应,并且 $sum(E) = \frac{sum(C)}{x}, sum(F) = \frac{sum(D)}{x}$,其中 $x = 2^k$。由于 $sum(C) = sum(D)$,因此 $sum(E) = sum(F)$,即 $E, F$ 是 $A$ 的合法划分,这与 $A$ 不可划分矛盾。
时间复杂度 $O(n^2a_i)$。
#include <cstring>
#include <iostream>
#define endl "\n"
#define x first
#define y second
#define lb(x) (x & -x)
using namespace std;
using PII = pair<int, int>;
constexpr int N = 110, M = 1000010, Q = 2050;
int n;
int a[N];
int z[Q];
bool f[M];
bool part() {
int s = 0;
for (int i = 1; i <= n; i++) s += a[i];
if (s & 1) return false;
int m = s >> 1;
memset(f, 0, min(M, m + 10));
f[0] = true;
for (int i = 1; i <= n; i++)
for (int j = m; j >= a[i]; j--)
f[j] |= f[j - a[i]];
return f[m];
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
if (!part()) cout << 0 << endl;
else {
for (int i = 0; i <= 11; i++) z[1 << i] = i;
PII ans = {11, 0};
for (int i = 1; i <= n; i++)
ans = min(ans, {z[lb(a[i])], i});
cout << 1 << endl << ans.y << endl;
}
}
int main() {
cin.tie(0)->sync_with_stdio(0);
solve();
return 0;
}