【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\n",query(K,s-x,x));
		}
	}
	return 0;
}
posted @ 2018-05-15 20:39  AutSky_JadeK  阅读(202)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト