题目大意:给出n个字符串,选择尽量多的串,使得各字母出现次数为偶数。
分析:见白书分析。另外,写一下自己对折半搜索的想法。首先,我们需要确定搜什么,然后对该对象进行折半,接着就是取与不取的问题了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
const int maxn = 30;
map<int, int> table;
char s[1000];
int n, A[maxn];
int bitcount(int x) { return x == 0 ? 0 : bitcount(x>>1)+(x&1); }
int main() {
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++) {
scanf("%s", s);
A[i] = 0;
for(int j = 0; s[j] != '\0'; j++)
A[i] ^= (1<<(s[j]-'A'));
}
table.clear();
int n1 = n/2, n2 = n-n1;
for(int i = 0; i < (1<<n1); i++) {
int x = 0;
for(int j = 0; j < n1; j++)
if(i & (1<<j)) x ^= A[j];
if(!table.count(x) || bitcount(table[x]) < bitcount(i)) table[x] = i;
}
int ans = 0;
for(int i = 0; i < (1<<n2); i++) {
int x = 0;
for(int j = 0; j < n2; j++)
if(i & (1<<j)) x ^= A[n1+j];
if(table.count(x) && bitcount(ans) < bitcount(table[x])+bitcount(i)) ans = (i<<n1)^table[x];
}
printf("%d\n", bitcount(ans));
for(int i = 0; i < n; i++)
if(ans & (1<<i)) printf("%d ", i+1);
printf("\n");
}
return 0;
}