• uvalive 2965 Jurassic Remains


    https://vjudge.net/problem/UVALive-2965

     题意:

    给出若干个由大写字母组成的字符串,要求选出尽量多的字符串,使得每个大写字母出现的次数是偶数。

    思路:

    如果说我们把每个字母映射为不同的数字,那么每个字符串就可以用不同的数字来表示,即按照二进制位转化各个字符。

    如ABCD既可以表示为1111,ABCE可以表示为11101。

    那么问题就转化成了给出n个数字,那么选择尽量多的数字使得他们的异或为0(每个字符出现偶数次,则他们的异或肯定为0)。

    一开始我直接用的2^N的状态压缩但是t了,参考了训练指南,之后复杂度降为1.414^(N) * log(N)。

    先把前n/2个数可以得到的数字用一个map存起来,之后枚举后面n - n/2个数可以得到的结果,直接在map里面寻找位数尽量大的就可以了。

    求一个数的二进制位有多少个1,这题十分巧妙的用了二分。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <vector>
     4 #include <map>
     5 using namespace std;
     6 
     7 int a[30];
     8 
     9 vector<int> rec;
    10 map<int,int> mmp;
    11 
    12 int calbit(int x)
    13 {
    14     if (x == 0) return 0;
    15 
    16     return calbit(x / 2) + (x & 1);
    17 }
    18 
    19 int main()
    20 {
    21     int n;
    22 
    23     while (scanf("%d",&n) != EOF)
    24     {
    25         mmp.clear();
    26         rec.clear();
    27 
    28         for (int i = 0;i < n;i++)
    29         {
    30             int tmp = 0;
    31 
    32             char b[30];
    33 
    34             scanf("%s",b);
    35 
    36             for (int j = 0;j < strlen(b);j++)
    37             {
    38                 tmp ^= (1 << (b[j] - 'A'));
    39             }
    40 
    41             a[i] = tmp;
    42         }
    43 
    44         int n1 = n / 2;
    45         int n2 = n - n1;
    46 
    47         for (int i = 0;i < (1 << n1);i++)
    48         {
    49             int tmp = 0;
    50 
    51             for (int j = 0;j < n1;j++)
    52             {
    53                 if (i & (1 << j)) tmp ^= a[j];
    54             }
    55 
    56             if (mmp.find(tmp) != mmp.end() || calbit(mmp[tmp]) < calbit(i)) mmp[tmp] = i;
    57         }
    58 
    59         int ans = 0;
    60 
    61         for (int i = 0;i < (1 << n2);i++)
    62         {
    63             int tmp = 0;
    64 
    65             for (int j = 0;j < n2;j++)
    66             {
    67                 if (i & (1 << j)) tmp ^= a[n1+j];
    68             }
    69 
    70             if (mmp.find(tmp) != mmp.end())
    71             {
    72                 if (calbit(i) + calbit(mmp[tmp]) > calbit(ans)) ans = mmp[tmp] ^ (i << n1);
    73             }
    74         }
    75 
    76         for (int i = 0;i < n;i++)
    77         {
    78             if (ans & (1 << i)) rec.push_back(i);
    79         }
    80 
    81         printf("%d
    ",rec.size());
    82 
    83         for (int i = 0;i < rec.size();i++)
    84         {
    85             printf("%d%c",rec[i] + 1,i == rec.size() ? '
    ': ' ');
    86         }
    87 
    88         printf("
    ");
    89     }
    90 
    91     return 0;
    92 }
  • 相关阅读:
    求大神回答这个管理系统不知道为啥不成功急!
    这个函数到底什么意思如何调用
    判断浮点数是否为零的问题
    字符串与列表的 常用方法
    变量名命名规范 运算符 流程控制
    ACM C++
    struts s:iterator循环遍历数据 自动生成序号
    JAVA将一个EXCEL多行订单产品字符串分解成一个个子订单 +连接符连接
    JS在HTML中获取到所有选中的checkbox的值
    自己做的java-WEB项目。希望360浏览器能够默认使用极速模式打开
  • 原文地址:https://www.cnblogs.com/kickit/p/7677977.html
Copyright © 2020-2023  润新知