題意:
給定n個大寫字母組成的字符串,選擇儘量多的串,使得每個大寫字母都能出現偶數次
分析:
不難想出枚舉每個字符串選擇與否的暴力算法可惜運算量高達2^24
由於字符串只考慮每個字母的奇偶情況,用0表示字符出現的次數爲偶數,1表示出現的次數爲基數,可以使用stl中的map建立前n/2個字符串所有情況的映射,然後枚舉後n個的時候可以從映射中二分查找
Code:
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define DIR 4
#define DIM 2
#define STATUS 2
#define MAXBIT 24
#define MAXN 20 + 10
#define MAXM 100000 + 10
#define oo (~0u)>>1
#define INF 0x3F3F3F3F
#define REPI(i, s, e) for(int i = s; i <= e; i ++)
#define REPD(i, e, s) for(int i = e; i >= s; i --)
static const double EPS = 1e-5;
char str[MAXN];
int f[MAXN];
map<int, int> hash;
map<int, int>::iterator it;
int count_bit(int value)
{
if( !value ) {
return 0;
}
return count_bit(value>>0x1)+(value&1);
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif
int n;
while( ~scanf("%d", &n) ) {
hash.clear();
REPI(i, 1, n) {
scanf("%s", str);
f[i] = 0;
REPI(j, 0, strlen(str)-1) {
f[i] ^= (1<<(str[j]-'A'));
}
}
//enum the first part, n/2
int n1 = n>>0x1;
int value;
REPI(i, 0, (1<<n1)-1) {
value = 0;
REPI(j, 0, n1-1) {
if( i&(1<<j) ) { //select (j+1)
value ^= f[j+1];
}
}
it = hash.find(value);
if( it == hash.end() ) {
hash.insert(map<int, int>::value_type(value, i));
}
else if( count_bit(it->second) < count_bit(i) ) {
it->second = i;
}
}
// //enum the second part.
int n2 = n-n1;
int count = 0, lans = 0, rans = 0;
REPI(i, 0, (1<<n2)-1) {
value = 0;
REPI(j, 0, n2-1) {
if( i&(1<<j) ) {
value ^= (f[n1+j+1]);
}
}
it = hash.find(value);
if( it == hash.end() ) {
continue;
}
int tmp = count_bit(it->second)+count_bit(i);
if( count < tmp ) {
lans = it->second, rans = i;
count = tmp;
}
}
//output ans.
printf("%d\n", count);
REPI(i, 0, n1-1) {
if( lans&(1<<i) ) {
printf("%d ", i+1);
}
}
REPI(i, 0, n2-1) {
if( rans&(1<<i) ) {
printf("%d ", n1+i+1);
}
}
printf("\n");
}
return 0;
}