【中途相遇+二进制】【NEERC 2003】Jurassic Remains
例题25 侏罗纪(Jurassic Remains, NEERC 2003, LA 2965)
给定n个大写字母组成的字符串。选择尽量多的串,使得每个大写字母都能出现偶数次。
【输入格式】
输入包含多组数据。每组数据的第一行为正整数n(1≤n≤24),以下n行每行包含一个大写字母组成的字符串。
【输出格式】
对于每组数据,第一行输出整数k,即字符串个数的最大值。第二行按照从小到大的顺序输出选中的k个字符串的编号(字符串按照输入顺序编号为1~n)。
【样例输入】
6
ABD
EG
GE
ABE
AC
BCD
【样例输出】
5
1 2 3 5 6
直接贴题解吧
在一个字符串中,每个字符出现的次数本身是无关紧要的,重要的只是这些次数的奇偶性,因此想到用一个二进制的位表示一个字母(1表示出现奇数次,0表示出现偶数次)。比如样例的6个数,写成二进制后如图1-34所示。
图 1-34
此时,问题转化为求尽量多的数,使得它们的xor(异或)值为0。
最容易想到的方法是直接穷举,时间复杂度为O(2n),有些偏大。注意到xor值为0的两个整数必须完全相等,我们可以把字符串分成两个部分:首先计算前n/2个字符串所能得到的所有xor值,并将其保存到一个映射S(xor值à前n/2个字符串的一个子集)中;然后枚举后n/2个字符串所能得到的所有xor值,并每次都在S中查找。
如果映射用STL的map实现,总时间复杂度为O(2n/2logn),即O(1.44nlogn),比第一种方法好了很多。这样的策略称为中途相遇法(Meet-in-the-Middle)。密码学中著名的中途相遇攻击(Meet-in-the-Middle attack)就是基于这个原理。
#include<cstdio>
#include<map>
using namespace std; const int maxn = 24;
map<int,int> table; int bitcount(int x) { return x == 0 ? 0 :bitcount(x/2) + (x&1); } int main() {
int n,A[maxn];
chars[1000]; while(scanf("%d", &n) == 1 && n) {
//输入并计算每个字符串对应的位向量
for(int i= 0; i < n; i++) {
scanf("%s", s);
A[i] =0;
for(intj = 0; s[j] != '\0'; j++) A[i] ^= (1<<(s[j]-'A'));
}
//计算前n1个元素的所有子集的xor值
//table[x]保存的是xor值为x的,bitcount尽量大的子集
table.clear();
int n1 =n/2, n2 = n-n1;
for(int i= 0; i < (1<<n1); i++) {
int x =0;
for(intj = 0; j < n1; j++) if(i & (1<<j)) x ^= A[j];
if(!table.count(x) || bitcount(table[x]) < bitcount(i)) table[x] = i;
}
//枚举后n2个元素的所有子集,并在table中查找
int ans =0;
for(int i= 0; i < (1<<n2); i++) {
int x =0;
for(intj = 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;
}
几个位运算以及STL巧妙运用注意注意
int bitcount(int x) //计算一串数的二进制还有的1的个数
table.count(x)//判断x是否为控
ans = (i<<n1)^table[x];//合并i与x 两个二进制代表的集合
【中途相遇+二进制】【NEERC 2003】Jurassic Remains的更多相关文章
- LA 2965 Jurassic Remains (中途相遇法)
Jurassic Remains Paleontologists in Siberia have recently found a number of fragments of Jurassic pe ...
- 【UVALive】2965 Jurassic Remains(中途相遇法)
题目 传送门:QWQ 分析 太喵了~~~~~ 还有中途相遇法这种东西的. 嗯 以后可以优化一些暴力 详情左转蓝书P58 (但可能我OI生涯中都遇不到正解是这个的题把...... 代码 #include ...
- UVALive - 2965 Jurassic Remains (LA)
Jurassic Remains Time Limit: 18000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu [Sub ...
- 【中途相遇法】【STL】BAPC2014 K Key to Knowledge (Codeforces GYM 100526)
题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show& ...
- 【UVALive2965】Jurassic Remains
题意 题意给定n个大写字母组成的字符串,选择尽量多的串,使得每个大写字母都能出现偶数次.n<=24,每个字符串中每个字母最多出现一次. 分析 这是训练指南上的一道中途相遇法的简单题,但是好像也能 ...
- LA 2965 中途相遇法
题目链接:https://vjudge.net/problem/UVALive-2965 题意: 有很多字符串(24),选出一些字符串,要求这些字符串的字母都是偶数次: 分析: 暴力2^24也很大了, ...
- 中途相遇法 解决 超大背包问题 pack
Description [题目描述] 蛤布斯有n个物品和一个大小为m的背包,每个物品有大小和价值,它希望你帮它求出背包里最多能放下多少价值的物品. [输入数据] 第一行两个整数n,m.接下来n行每行两 ...
- uva 6757 Cup of Cowards(中途相遇法,貌似)
uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 different characters (M ...
- HDU 5936 Difference 【中途相遇法】(2016年中国大学生程序设计竞赛(杭州))
Difference Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
随机推荐
- ADO.NET程序访问数据的组件
组成--数据集(内存中的数据库) --DataSet数据集 --DataTable数据表 --DataColumn数据列 --DataRow数据行 --DataView数据视图--NET数据提供程序 ...
- AsyncTask使用注意事项
AsyncTask是android自带的一个异步处理线程 它带了很多参数 都很方便使用 但是有一些注意事项 1: 官网说明: AsyncTasks should ideally be used for ...
- UINavigationController 导航控制器
一.导航视图控制器 1.管理视图控制器 2.控制视图控制器之间的跳转 3.是以压栈和出栈的形式来管理视图控制器 4.导航视图控制器必须要设置根视图控制器 5.导航是视图控制器包含UINavigatio ...
- c#窗体的传值方法
了解了窗体的显示相关知识,接着总结一下窗体的传值方法: .通过构造函数 特点:传值是单向的(不可以互相传值),实现简单 实现代码如下: 在窗体Form2中 int value1; ...
- Struts2中的ActionContext
ActionContext(Action上下文) ActionContext介绍 通过上面用户注册例子的学习,我们知道Xwork与Web无关性,我们的Action不用去依赖于任何Web容器,不用和那些 ...
- C++服务器设计(三):多线程模型设计
多线程探讨 如今大多数CPU都具有多个核心,为了最大程度的发挥多核处理器的效能,提高服务器的并发性,保证系统对于多线程的支持是十分必要的.我们在之前的设计都是基于单线程而言,在此章我们将对系统进行改进 ...
- BestCoder Round #36 (hdu5198)Strange Class(水题)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Strange Class Time Limit: 2000/1000 MS (J ...
- ExtJS 创建动态加载树
Ext 中导航树的创建有两种方式:1.首先将所有的数据读出来,然后绑定到前台页面.2.每点击一个节点展开后加载子节点.在数据量比较小的时候使用第一种方式加载的会快一些,然而当数据量比较大的时候,我还是 ...
- DOM 对象之 document.all
1.document.all是页面内所有元素的一个集合: 2.经测试在chrome,safari,opera,ie中均返回一个HTMLALLCollection[xx]对象,在FF中返回是一个unde ...
- mysql install
./scripts/mysql_install_db --user=mahao01 --basedir=/home/mahao01/local/mysql --datadir=/home/mahao0 ...