Jurassic Remains(LA 2965)位运算+枚举
来源:互联网 发布:网络推广部职责 编辑:程序博客网 时间:2024/06/05 19:23
来自《算法竞赛入门经典训练指南》
1.题目原文
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=966
md,英语根本读不下去啊啊啊啊啊啊啊啊。
给定n个大写字母组成的字符串,选择尽可能多的字符串,使得每个大写字母都能出现偶数次。
2.解题思路
在一个字符串中,每个字母的出现次数无关紧要,重要的是出现次数的奇偶性。因此想到可以用一个二进制的位表示一个字母(1表示出现奇数次,0表示出现偶数次)。
样例写成二进制如下:
A B C D E F G H ……
1 1 0 1 0 0 0 0…… A B D
0 0 0 0 1 0 1 0 ……E G
0 0 0 0 1 0 1 0…… E G
1 1 0 0 1 0 0 0……A B E
1 0 1 0 0 0 0 0……A C
0 1 1 1 0 0 0 0……B C D
此问题转化为求尽可能多的数,使得它们得xor值为0.
可以最容易想到的是直接穷举,时间复杂度为O(2^n),有些偏大。注意到xor值为0的两个数必须完全相等。因此,我们可以把字符串分成两部分:首先计算前半部分字符串所有的xor值,并将其保存到一个映射S(xor值→ 前n/2个字符串的一个子集)中,后半部分字符串枚举所有能得到的xor值,并每次都在S中查找。
如果映射用map实现,总时间复杂度为O(2^(n/2)logn)=O(1.414^n*logn)。这样的策略成为中途相遇法(Meet-in-the-Middle)。密码学中著名的中途相遇攻击(Meet-in-the-Middle-attack)就是基于这个原理。
3.AC代码
#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <set>#include <vector>#include<cmath>#include<bitset>#include<sstream>using namespace std;using namespace std;#define INF 0x7ffffffftypedef long long ll;const int maxn=30;map<int,int> table;int n;int A[maxn];char s[1000];//整数x在二进制表示下有多少位是1int bitcount(int x){ return x==0?0:bitcount(x/2)+(x&1);}int main(){ while(scanf("%d",&n)!=EOF&&n){ for(int i=0;i<n;i++){ scanf("%s",s); A[i]=0; for(int j=0;s[j]!='\0';j++){ A[i]^=(1<<(s[j]-'A')); } } //计算前一半元素的所有子集的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(int j=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(int j=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;}
0 0
- Jurassic Remains(LA 2965)位运算+枚举
- UVA 1326 - Jurassic Remains(技巧枚举+位运算)
- LA 2965 - Jurassic Remains 中途相遇法
- LA 2965 Jurassic Remains / 中途相遇法
- LA 2965 Jurassic Remains 中途相遇法 .
- UVA 1326 - Jurassic Remains(位运算)
- UVALive - 2965 Jurassic Remains (折半枚举法)
- LA --- 2965 Jurassic Remains 数相同的大写字母 【思维 + 状态压缩枚举 + 中途相遇法(折半搜索)】
- uva 1326 Jurassic Remains(中途相遇法+位运算)
- 2965 - Jurassic Remains
- uva 1326 - Jurassic Remains(暴力+位运算+中间相遇法)
- Jurassic Remains
- Jurassic Remains
- 【UVALive】2965 Jurassic Remains 中途相遇法
- POJ 1903 - Jurassic Remains 中途相遇法(枚举)
- POJ 1903 & ZOJ 2469 & UVA 1326 Jurassic Remains (部分枚举)
- POJ-1903-Jurassic Remains
- uva 1326 - Jurassic Remains
- JAVA中关于Map的九大问题
- javaweb工作原理
- 极限定义
- 哈夫曼树--最优二叉树
- Android 多手机 屏幕演示,同步控制,群控系统
- Jurassic Remains(LA 2965)位运算+枚举
- java集合1——collection的基础知识
- 解决ExpandableListView数据无法及时更新
- pacman参数入门
- Android 锁屏弹窗
- Linux信号处理
- 硬件
- PagerAdapter适配有条目,但是空白?
- C和指针读书笔记(第十三章)