LA2965 n个数中选出最多个数异或和为0
intput
n 1<=n<=24
n串只有大写字母的字符串
output
选出最多个字符串且每个大写字母出现的次数为偶数
第一行输出个数x
第二行输出x个字符串的下标
做法:将每个字符串转化为一个26bit数,1为奇数个大写字母,0为偶数个,则转化为找出最多个数异或和为0,直接枚举为O((2^n)*n),但只有a^a=0,所以将n个数分为两半(中途相遇法),复杂度降为O((2^(n/2))logn)
注意:异或和左半为0和右半为0的要特判,且右半要全部判完,因为可能出现2+3<5+1
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #define MAX 100000 13 14 using namespace std; 15 struct node 16 { 17 int mark,n; 18 node operator+(const node&b)const 19 { 20 return (node){mark|b.mark,n+b.n}; 21 } 22 bool operator<(const node&a)const 23 { 24 return n<a.n; 25 } 26 }; 27 int a[30],c[26],n,ch,num; 28 char s[1000]; 29 node maxn; 30 map<int,node>q; 31 map<int,node>::iterator qsum; 32 void dfs(int x,int mark,int sum,int nn) 33 { 34 if(x==n>>1) 35 { 36 q.insert(make_pair(sum,(node){mark,nn})); 37 if(sum==0) maxn=max(maxn,(node){mark,nn}); 38 return; 39 } 40 sum^=a[x]; 41 nn++; 42 mark|=1<<x; 43 dfs(x+1,mark,sum,nn); 44 sum^=a[x]; 45 nn--; 46 mark&=~(1<<x); 47 dfs(x+1,mark,sum,nn); 48 } 49 void find(int x,int mark,int sum,int nn) 50 { 51 if(x==n) 52 { 53 qsum=q.find(sum); 54 if(qsum!=q.end()) maxn=max(maxn,qsum->second+(node){mark,nn}); 55 if(sum==0) maxn=max(maxn,(node){mark,nn}); 56 return; 57 } 58 sum^=a[x]; 59 nn++; 60 mark|=1<<x; 61 find(x+1,mark,sum,nn); 62 sum^=a[x]; 63 nn--; 64 mark&=~(1<<x); 65 find(x+1,mark,sum,nn); 66 } 67 int main() 68 { 69 freopen("/home/user/桌面/in","r",stdin); 70 while(scanf("%d%*c",&n)==1) 71 { 72 memset(a,0,sizeof(a)); 73 for(int i=0;i<n;i++) 74 { 75 memset(c,0,sizeof(c)); 76 scanf("%s",s); 77 for(int j=0;s[j];j++) c[s[j]-'A']++; 78 for(int j=0;j<26;j++) if(c[j]&1) a[i]|=1<<j; 79 } 80 if(n==1) 81 { 82 if(a[0]) puts("0\n"); 83 else puts("1\n1"); 84 continue; 85 } 86 q.clear(); 87 maxn=(node){0,0}; 88 dfs(0,0,0,0); 89 find(n>>1,0,0,0); 90 if(maxn.n) 91 { 92 printf("%d\n",maxn.n); 93 for(int i=0,j=0;i<n;i++) 94 { 95 if(maxn.mark&(1<<i)) 96 { 97 if(j) putchar(' '); 98 printf("%d",i+1); 99 j=1; 100 } 101 } 102 printf("\n"); 103 } 104 else puts("0\n"); 105 } 106 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 107 return 0; 108 }