UVA1326 Jurassic Remains

UVA1326 Jurassic Remains

知识点:集合的整数表示 + 折半枚举 +异或

一.题意

选择最多的串,使得这些串中出现的每一位大写字母都是出现了偶数次,并且输出串的个数,和按照升序说出选择了哪几个串

二.题解

把二进制上的每一位当作是一个大写字母(A->1,B->2,C->4……),然后通过异或来判断出现的次数是奇次还是偶次,并且通过折半枚举,将n分成两半来枚举

#include<stdio.h>
#include<string.h>
#include<set>
#include<map>
#include<string>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long ll;

int n,a[30];
map <int,int> table;

int bitcount(int x){	//求x对应二进制中1的个数 
	return (x == 0 ? 0 : (x & 1) + bitcount(x>>1));
}

int main(){
	while(cin>>n){
		string s;
		for(int i = 0; i < n; i++){
			cin>>s;
			a[i] = 0;
			for(int j = 0; j < s.size(); j++)
				//记录第i串中出现的每个字母的奇偶,奇数次为1,偶数次为0 
				a[i] ^= (1 <<  (s[j] - 'A'));	
		}
		
		//将n分成两半 
		int left = n/2;
		int right = n - left;
		
		//多组数据,每次清空table表 
		table.clear();
		
		for(int i = 0; i < (1<<left); i++){ //枚举含有全部n/2个元素的集合 
			int x = 0;
			for(int j = 0; j < left; j++)	if(i >> j & 1)//当i >> j为1时就代表选择了第j串 
				x ^= a[j];
			
			//x没出现过或者更新为一个同样得到结果为x,但是选择了更多串的结果	
			if(!table.count(x) || bitcount(table[x]) < bitcount(i))
				table[x] = i;
		}
		
		int res = 0;
		for(int i = 0; i < (1<<right); i++){
			int x = 0;
			for(int j = 0; j < right; j++)	if(i >> j & 1)
				x ^= a[left + j];
			//如果这个x出现过那么异或结果就为0,即出现过的每个大写字母都是偶数次
			//并且每次更新为选择串更多的结果	
			if(table.count(x) && bitcount(res) < (bitcount(table[x]) + bitcount(i)))
				//别忘记前面还有选择了的串,就把前面的串向左移动left位,在异或table[x] 
				res = (i<<left) ^ table[x];
		}
		
		printf("%d\n",bitcount(res));
		
		int k = 1;
		while(res){
			if(res & 1)
				printf("%d ",k);
			k++;
			res >>= 1;
		}
		puts("");
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值