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
");
 83             else puts("1
1");
 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
",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("
");
103         }
104         else puts("0
");
105     }
106     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
107     return 0;
108 }
View Code
原文地址:https://www.cnblogs.com/cdyboke/p/4996773.html