UVa 1326 - Jurassic Remains

题意

找出尽量多的串,使每个字母都出现偶数次

思路

因为N<=24,考虑状态压缩。而对于每一个状态,可以用1表示出现奇数,0表示出现偶数,再对一个串中的字母进行状态压缩。

但是如果一直^到最后,复杂度为 O(2n) ,TLE。考虑枚举一半的串的状态,然后在后一半中查找。因为只有两个相同的状态值异或才可以符合条件。

这样复杂度就变成 O(1.414n)

代码

 
 
  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define lowbit(x) ((x) & (-x))
  4. #define MP(a, b) make_pair(a, b)
  5. const int MAXN = 30 + 5;
  6. const int INF = 0x3f3f3f3f;
  7. using namespace std;
  8. typedef pair<int, int> pii;
  9. typedef vector<int> vei;
  10. typedef vector<pair<int, int> >veii;
  11. typedef vector<int>::iterator viti;
  12. typedef vector<pii>::iterator vitii;
  13. typedef priority_queue<pii, vector<pii>, greater<pii> >pquii;
  14. char word[1000];
  15. int num[MAXN];
  16. map<int, int> mp;
  17. int BitCount(int x)
  18. {
  19. return x == 0 ? 0 : BitCount(x >> 1) + (x & 1);
  20. }
  21. int main()
  22. {
  23. //freopen("input.txt", "r", stdin);
  24. int n, i, j;
  25. while (~scanf("%d", &n))
  26. {
  27. mp.clear();
  28. for (i = 0; i < n; i++)
  29. {
  30. scanf("%s", word);
  31. num[i] = 0;
  32. for (j = 0; word[j]; j++)
  33. num[i] ^= (1 << (word[j] - 'A'));
  34. }
  35. int n1 = n / 2, n2 = n - n1;
  36. for (int state = 0; state < (1 << n1); state++)
  37. {
  38. int cur = 0;
  39. for (i = 0; i < n; i++)
  40. if ((1 << i) & state) cur ^= num[i];
  41. if (!mp.count(cur) || BitCount(mp[cur]) < BitCount(state)) mp[cur] = state;
  42. }
  43. int ans = 0;
  44. for (int state = 0; state < (1 << n2); state++)
  45. {
  46. int cur = 0;
  47. for (int i = 0; i < n2; i++) if (state & (1 << i)) cur ^= num[n1 + i];
  48. if (mp.count(cur) && BitCount(ans) < BitCount(mp[cur]) + BitCount(state))
  49. ans = (state << n1) ^ mp[cur];
  50. }
  51. bool first = true;
  52. printf("%d\n", BitCount(ans));
  53. for (i = 0; i < n; i++)
  54. if ((1 << i) & ans)
  55. {
  56. if (first)
  57. printf("%d", i + 1), first = false;
  58. else printf(" %d", i + 1);
  59. }
  60. puts("");
  61. }
  62. return 0;
  63. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值