题目链接:这里
题意:给出n个IPv4的子网地址,格式是a-b-c-d/l,a b c d l都是十进制数,然后l是网络地址的长度,最长到32,要求输出最低限度的所有的未能划分出的子网地址,这些子网和给出的n个子网没有交集,这些地址和给出的n个地址能组成完整的网络地址。
解法:把所有的ip地址***字典树,并且标记单词节点,之后然后暴力递归找所有未被包含在已有子网里的子网地址。其实就是trie树上暴力。。。。不过题意看pdf看了超久,还是在网上的解题报告弄清题意的,读题需要训练了。

//LA 7043

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;

struct Trie{
    struct node{
        int a, b, c, d, l;
        node(){}
        node(int a, int b, int c, int d, int l) : a(a), b(b), c(c), d(d), l(l) {}
    };
    int n, cnt, ans[40];
    char s[40];
    vector <node> v;
    int root, sz, ch[maxn][2], flag[maxn];
    void get(int x){
        for(int i = 7; i >= 0; i--){
            if((x>>i)&1) s[cnt++] = '1';
            else s[cnt++] = '0';
        }
    }
    void init(){
        root = 0;
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
        v.clear();
    }
    void insert(char *s, int len){
        int u = root;
        for(int i = 0; i < len; i++){
            int now = s[i] - '0';
            if(!ch[u][now]){
                memset(ch[sz], 0, sizeof(ch[sz]));
                flag[sz] = 0;
                ch[u][now] = sz++;
            }
            u = ch[u][now];
        }
        flag[u] = 1;
    }
    void query(int u, int cur){
        if(flag[u]) return;
        for(int j = 1; j >= 0; j--){
            ans[cur] = j;
            if(ch[u][j]){
                query(ch[u][j], cur+1);
            }
            else{
                int a, b, c, d;
                int tt, l, r;
                tt = 0, l = 0, r = 7;
                for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
                a = tt;
                tt = 0, l = 8, r = 15;
                for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
                b = tt;
                tt = 0, l = 16, r = 23;
                for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
                c = tt;
                tt = 0, l = 24, r = 31;
                for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
                d = tt;
                v.push_back(node(a, b, c, d, cur));
            }
        }
    }
    void run(){
        int T, ks = 0;
        scanf("%d", &T);
        while(T--){
            init();
            scanf("%d", &n);
            printf("Case #%d:\n", ++ks);
            if(n == 0){
                printf("1\n");
                printf("0.0.0.0/0\n");
            }
            else{
                for(int i = 0; i < n; i++){
                    int a, b, c, d, l;
                    scanf("%d.%d.%d.%d/%d", &a, &b, &c, &d, &l);
                    cnt = 0;
                    get(a), get(b), get(c), get(d);
                    s[cnt] = 0;
                    insert(s, l);
                }
                query(0, 0);
                cout << v.size() << endl;
                for(int i = 0; i < (int)v.size(); i++){
                    printf("%d.%d.%d.%d/%d\n", v[i].a, v[i].b, v[i].c, v[i].d, v[i].l + 1);
                }
            }
        }
    }
}ac;
int main()
{
    ac.run();
    return 0;
}