zoukankan      html  css  js  c++  java
  • 【Trie】【枚举约数】Codeforces Round #482 (Div. 2) D. Kuro and GCD and XOR and SUM

    题意:

    给你一个空的可重集,支持以下操作:

    向其中塞进一个数x(不超过100000),

    询问(x,K,s):如果K不能整除x,直接输出-1。否则,问你可重集中所有是K的倍数的数之中,小于等于s-x,并且与x异或结果最大的数是多少(如果不存在这样的数,也输出-1)。

    建立100000个二进制Trie,第i个Trie中存储i的所有倍数。

    查询的时候,在Trie上从高位到低位贪心地找,如果从根到当前点的路径形成的数恰好与s-x相等,要从当前点进行一次dfs统计,看看当前子树中是否存在不超过s-x的数,如果不存在,返回-1。如果当前位恰好小于s-x的当前位,开启一个“限制解除”标记。如果已经开启了此标记,直接返回该点的子树大小是否大于零即可,不必dfs统计。如果没有开启此标记,并且当前位大于s-x的当前位,直接返回-1即可。

    #include<cstdio>
    using namespace std;
    struct Node{
    	int ch[2];
    	Node(){
    		ch[0]=ch[1]=0;
    	}
    };
    Node* trees[100005];
    int *sz[100005];
    int tot[100005];
    bool vis[100005];
    void Insert(int o,int x){
    	int U=1;
    	++sz[o][1];
        for(int i=18-1;i>=0;--i){
        	if(!trees[o][U].ch[(x>>i)&1]){
        		trees[o][U].ch[(x>>i)&1]=++tot[o];
        	}
    		U=trees[o][U].ch[(x>>i)&1];
    		++sz[o][U];
    	}
    }
    void Insert(int x){
    	if(vis[x]){
    		return;
    	}
    	vis[x]=1;
    	for(int i=1;i*i<=x;++i){
    		if(x%i==0){
    			if(i!=x/i){
    				Insert(i,x);
    				Insert(x/i,x);
    			}
    			else{
    				Insert(i,x);
    			}
    		}
    	}
    }
    bool jiechu;
    bool check(int o,int Bit,int lim,int i,int U){
    	if(jiechu || Bit<(lim>>(i-1)&1)){
    		return sz[o][U];
    	}
    	if(Bit>(lim>>(i-1)&1)){
    		return 0;
    	}
    	int sum=0;
    	for(--i;i>=1;--i){
    		int limBit=(lim>>(i-1)&1);
    		if(limBit==1){
    			sum+=sz[o][trees[o][U].ch[0]];
    		}
    		U=trees[o][U].ch[limBit];
    	}
    	sum+=sz[o][U];
    	return sum>0;
    }
    int query(int o,int lim,int W){
    	jiechu=0;
    	int res=0,U=1;
        for(int i=18;i>=1;--i){
            int Bit=((W>>(i-1)&1)^1);
            if(!check(o,Bit,lim,i,trees[o][U].ch[Bit])){
            	Bit^=1;
            	if(!check(o,Bit,lim,i,trees[o][U].ch[Bit])){
            		return -1;
            	}
            }
            if(Bit<(lim>>(i-1)&1)){
            	jiechu=1;
            }
            res+=(1<<(i-1))*Bit;
            U=trees[o][U].ch[Bit];
        }
        return res;
    }
    int q;
    int main(){
    	int op,x,K,s;
    	for(int i=1;i<=100000;++i){
    		tot[i]=1;
    		trees[i]=new Node[20*100000/i];
    		sz[i]=new int[20*100000/i];
    		for(int j=0;j<20*100000/i;++j){
    			sz[i][j]=0;
    		}
    	}
    	scanf("%d",&q);
    	for(;q;--q){
    		scanf("%d%d",&op,&x);
    		if(op==1){
    			Insert(x);
    		}
    		else{
    			scanf("%d%d",&K,&s);
    			if(x%K!=0 || s<=x){
    				puts("-1");
    				continue;
    			}
    			printf("%d
    ",query(K,s-x,x));
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    jstl与el学习笔记
    Subversion 安装笔记
    某公司面试
    字符集与字符编码的一些小常识,以及java web中文乱码的一些solution
    分治算法与合并排序示例
    C/C++ 笔试,难倒我哉
    HTML meat作用
    VIM配置DBGp调试PHP程序
    更新系统引导项
    PHP技术讨论群
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/9042921.html
Copyright © 2011-2022 走看看