CCF201812-3 CIDR合并(100分)位运算+文本

Posted 海岛Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF201812-3 CIDR合并(100分)位运算+文本相关的知识,希望对你有一定的参考价值。

试题编号: 201812-3
试题名称: CIDR合并
时间限制: 1.0s
内存限制: 512.0MB



样例输入
2
1
2

样例输出
1.0.0.0/8
2.0.0.0/8

样例输入
2
10/9
10.128/9

样例输出
10.0.0.0/8

样例输入
2
0/1
128/1

样例输出
0.0.0.0/0

问题链接CCF202104-1 灰度直方图
问题简述:(略)
问题分析:按题意进行处理即可,有2次合并处理。
程序说明:(略)
参考链接:(略)
题记:位运算巧妙,输入文本处理简洁。

AC的C++语言程序如下:

/* CCF201812-3 CIDR合并 */

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 1;
struct Node {
    unsigned int num;
    int len;
    bool flag;
} ip[N], ip2[N];
int ipcnt = 0;

bool cmp(Node a, Node b)
{
    return a.num == b.num ? a.len < b.len : a.num < b.num;
}

void iptok(char s[])
{
    unsigned int num[4] = {0, 0, 0, 0};
    int cnt = 0, len = 0, flag = 0;
    for (int i = 0; s[i]; i++)
        if (s[i] == '.') cnt++;
        else if (s[i] == '/') flag = 1;
        else {
            if (flag) len = len * 10 + s[i] - '0';
            else num[cnt] = num[cnt] * 10 + s[i] - '0';
        }

    if (flag == 0) {
        int pcnt = 0;
        for (int i = 0; s[i]; i++)
            if (s[i] == '.') pcnt++;
        len = pcnt * 8 + 8;
    }

    ip[++ipcnt].len = len;
    ip[ipcnt].flag = true;
    ip[ipcnt].num = (((num[0] * 256) + num[1]) * 256 + num[2]) * 256 + num[3];
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL);
    cout.tie(NULL);

    int n;
    char s[20];

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s;
        iptok(s);
    }

    sort(ip + 1, ip + 1 + n, cmp);

    int cnt = 1;
    ip2[cnt] = ip[cnt];
    for (int i = 2; i <= n; i++)
        for (int j = 0; j < ip2[cnt].len; j++)
            if (((ip[i].num >> (31 - j)) & 1) != ((ip2[cnt].num >> (31 - j)) & 1)) {
                ip2[++cnt] = ip[i];
                break;
            }

    for (; ;) {
        bool flag = false;
        int k;
        for (int i = 1; i <= cnt; i++)
            if (ip2[i].flag) {
                k = i;
                break;
            }
        for (int i = k + 1; i <= cnt; i++)
            if (ip2[i].flag) {
                if (ip2[i].len == ip2[k].len) {
                    for (int j = 0; j < ip2[i].len - 1; j++)
                        if (((ip2[i].num >> (31 - j)) & 1) != ((ip2[k].num >> (31 - j)) & 1)) {
                            k = i;
                            break;
                        }
                    if (k != i) {
                        ip2[k].len -= 1;
                        ip2[i].flag = false;
                        flag = true;
                    }
                } else
                    k = i;
            }
        if (!flag) break;
    }

    for (int i = 1; i <= cnt; i++)
        if (ip2[i].flag) {
            unsigned int a = ip2[i].num >> 24;
            unsigned int b = (ip2[i].num % (256 * 256 * 256)) >> 16;
            unsigned int c = (ip2[i].num % (256 * 256)) >> 8;
            unsigned int d = ip2[i].num % 256;

            cout << a << "." << b << "." << c << "." << d << "/" << ip2[i].len << endl;
        }

    return 0;
}

以上是关于CCF201812-3 CIDR合并(100分)位运算+文本的主要内容,如果未能解决你的问题,请参考以下文章

CCF 201709-3 JSON查询 100分

CCF 201709-3 JSON查询 100分

CCF 201312-4 有趣的数 100分(数位dp)

CCF 201312-4 有趣的数 100分(数位dp)

CCF 201312-4 有趣的数 100分(数位dp)

CCF 202009-2 风险人群筛查 100分