• HDU5269 字典树


      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5269 ,BestCoder Round #44的B题,关于字典树的应用。

      比赛的时候没想出做法,现在补上。


    题解:

      我们考虑,当lowbit(A xor B) = 2p时,A和B表示的二进制数的后p-1位肯定相同。于是我们可以维护一棵字典树,对于每个数x,可以将其转换为30位的二进制数(不足30位的在前面补0),将该二进制数逆序后插入字典树。统计答案时,对于Ai我们先将其同上述做法转换为30位的二进制数,然后逆序后在字典树中查找,对于路径上的每个结点x,如果它下一步对应的边是v,则和它xor后lowbit为2k的数有cnt(x , !v)个。cnt(x , v)表示x的对应的v这条边的子树个数。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <vector>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    const int maxn = 50000 + 10;
    const int MOD = 998244353;
    const int sigma_size = 2;
    struct Trie {
        int ch[maxn * 30][sigma_size];
        LL cnt[maxn * 30] , pow[35];
        int size;
        void init() {
            size = pow[0] = 1;
            memset(ch[0] , 0 , sizeof(ch[0]));
            memset(cnt , 0 , sizeof(cnt));
            for(int i = 1 ; i < 33 ; i++)    
                pow[i] = pow[i - 1] << 1; 
        }
        int index(char c)    {    return c - '0';    }
        void insert(char *s) {
            int i , rt;
            for(i = rt = 0 ; s[i] != '' ; i++) {
                int c= index(s[i]);
                if(!ch[rt][c]) {
                    memset(ch[size] , 0 , sizeof(ch[size]));
                    ch[rt][c] = size++;
                }
                rt = ch[rt][c];
                cnt[rt] = (cnt[rt] + 1) % MOD;
            }
        }
        LL find(char *s) {
            int i , rt;
            LL ret;
            for(i = rt = ret = 0 ; s[i] != '' ; i++) {
                int c = index(s[i]);
                if(ch[rt][!c]) {
                    int tmp = ch[rt][!c];
                    ret = (ret + (pow[i] * (1LL * cnt[tmp]))) % MOD;
                }
                rt = ch[rt][c];
            }
            return ret;
        }
    } trie;
    void binary(int x , char *s)
    {
        int i = 0;
        while(x) {
            s[i++] = x % 2 + '0';
            x >>= 1;
        }
        while(i < 31)    s[i++] = '0';
        s[i] = '';
    }
    int a[maxn];    char s[100];
    
    int main()
    {
        int n , T;
        cin >> T;
        for(int cas = 1 ; cas <= T ; cas++)
        {
            trie.init();
            scanf("%d" , &n);
            for(int i = 1 ; i <= n ; i++) {
                scanf("%d" , &a[i]);
                binary(a[i] , s);
                trie.insert(s);
            }
            LL ans = 0;
            for(int i = 1 ; i <= n ; i++) {
                binary(a[i] , s);
                ans = (ans + trie.find(s)) % MOD;
            }
            printf("Case #%d: %I64d
    " , cas , ans);
        }
        return 0;
    }
  • 相关阅读:
    词频统计
    第二周每周例行报告
    事务管理(ACID)
    Redis
    jar包和war包的区别
    CSS实现Loading加载动画
    如何实现“返回顶部”的页面效果
    PHP页面跳转-常见方法
    局域网络调试方式
    Thinkphp 统计数据库字段总值
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4589408.html
Copyright © 2020-2023  润新知