【中途相遇+二进制】【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 ...
随机推荐
- jquery使用load开展局部刷新没有效果
jquery使用load开展局部刷新没有效果 jquery使用load进行局部刷新没有效果我的代码 <html><head><meta charset="u ...
- js判断是否是数字通用写法
function isNumber(value){ var isNumber = value.match(/^(-?\d+)(\.\d+)?$/g) !=null; if(value.substrin ...
- 是什么让我想到开发NFinal
我是从01前开始就接触.net,那时.net还是1.0时代,很多东西都没有.后来.net出了2.0版本.从vs2005开始就使用Webform做网站.当时感觉.net能够拖来拖去,很厉害.参加工作后, ...
- iOS开发 ~应用程序设计理念:视图控制器(UIViewController)、视图(UIView)
应用程序设计理念:视图控制器(UIViewController).视图(UIView) 利用视图控制器(底层)管理视图(外观),一对一 1.视图的作用:负责显示的外观 2.视图控制器的作用:创建界面. ...
- javaScript给元素添加多个class
<html> <head> <style type="text/css"> .div2{ font-size:16px; color:orang ...
- java之package与import
我就以package与import开始吧. package的作用其实就是c++的namespace的作用,防止名字相同的类产生冲突,只是实现的机制不一样,java编译器在编译时,直接根据package ...
- Java IO6 :IO总结
字节流.字符流继承关系 前几篇文章讲解了字节流.字符流的使用,不过Java提供给用户的流类远不止此,限于篇幅原因,没办法一一讲解,而且也没有必要一一讲解,就像我在写博客的时候多次提到的,有问题的时候学 ...
- No1_2. 流程控制_java学习笔记
import java.util.Scanner; import java.lang.Math; public class HelloForWhile { /** * 文档注释,程序名称:HelloF ...
- 关于LayoutParams
每一个布局均有一个叫LayoutParams的内部类,如: LinearLayout.LayoutParams RelativeLayout.LayoutParams AbsoluteLayout ...
- 解决: AGPBI: {"kind":"error","text":"indicate that it is *not* an inner class.","sources":[{}]}
关于Gradle Console输出类似这样错误信息: AGPBI: {"kind":"error","text":"indica ...