zoukankan      html  css  js  c++  java
  • Codeforces Round #482 (Div. 2)

    D. Kuro and GCD and XOR and SUM

    字典树真好玩。。。

    牛老板提供的思路:建1e5个 字典树,每个数插入到以它的因子为根所在的字典树中,这样就实现了整除,当然gcd(k, x) = k是必须的

    然后如何保证v + x <= s 和 v ^ x 最大呢?

    对于v + x <= s,我们可以维护01字典树中,经过每个节点的最小值,这样我们在访问每个节点时,直接min + x <= s 判断是否成立即可, 不成立就不用往下走了,因为最小值都不成立。

    对于v ^ x最大,就是一般字典树思路了,~x与字典树比较选相同的位走,并且同时判断不等式条件就可以啦。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 50;
    struct node
    {
        int next[2];
        int v;
    };
    node tree[maxn * 200];
    int root[maxn];
    int sz = 1;
    void build(int p, int x)
    {
        if(!root[p]) root[p] = sz++;
        int tmp = root[p];
        for(int i = 20; i >= 0; i--)
        {
            int id = (x >> i) & 1;
            if(tree[tmp].next[id] == 0)
            {
                memset(tree[sz].next, 0, sizeof(tree[sz].next));
                tree[sz].v = 1e6;
                tree[tmp].next[id] = sz++;
            }
            tmp = tree[tmp].next[id];
            tree[tmp].v = min(tree[tmp].v, x);
        }
    }
    void match(int k, int s, int x)
    {
        int par = root[k];
        if(par == 0)
        {
            printf("-1
    ");
            return;
        }
        int fx = ~x;
       // printf("%d
    ", ((fx >> 1) & 1));
        int ans = 0;
        int flag = 0;
        for(int i = 20; i >= 0; i--)
        {
            int id = (fx >> i) & 1;
            if(tree[par].next[id] && (tree[tree[par].next[id]].v + x) <= s) ///维护最小值,表示最少存在这样的解
            {
                ans = tree[tree[par].next[id]].v;
                par = tree[par].next[id];
            }
            else if(tree[par].next[1 - id] && (tree[tree[par].next[1 - id]].v + x) <= s)
            {
                ans = tree[tree[par].next[1 - id]].v;
                par = tree[par].next[1 - id];
            }
            else
            {
                flag = 1;
                break;
            }
        }
        if(flag || (!ans))
        {
            printf("-1
    ");
        }
        else
        {
            printf("%d
    ", ans);
        }
    }
    int gcd(int a, int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    int main()
    {
        memset(root, 0, sizeof(root));
        int q; scanf("%d", &q);
        while(q--)
        {
            int t;
            scanf("%d", &t);
            if(t == 1)
            {
                int u; scanf("%d", &u);
                for(int i = 1; i * i <= u; i++)
                {
                    if(u % i == 0) ///i是u的因子
                    {
                        build(i, u);
                        build(u / i, u);
                    }
                }
            }
            else
            {
                int x, k, s;
                scanf("%d %d %d", &x, &k, &s);
                int g = gcd(k, x);
                if(g != k)
                {
                    printf("-1
    ");
                }
                else
                {
                    match(k, s, x);
                }
            }
        }
    }
    Code
  • 相关阅读:
    闭包问题
    二级联动多选器
    一个和与后台数据连接的模板get post put 以及延伸的query
    鼠标经过图片的小动画
    UITableViewCell中cell重用机制导致内容重复的方法
    iOS Button在ios6的系统上无法实现点击,在更高版本的系统上可以
    iOS 使用Reachability实时检测网络连接状况
    iOS Uibutton防止多按钮同时按下
    iOS plist文件的添加
    iOS Xcode cannot run using the selected device.
  • 原文地址:https://www.cnblogs.com/littlepear/p/9041937.html
Copyright © 2011-2022 走看看