【Trie】【枚舉約數】Codeforces Round #482 (Div. 2) D. Kuro and GCD and XOR and SUM

題意:spa

給你一個空的可重集,支持如下操做:blog

向其中塞進一個數x(不超過100000),it

詢問(x,K,s):若是K不能整除x,直接輸出-1。不然,問你可重集中全部是K的倍數的數之中,小於等於s-x,而且與x異或結果最大的數是多少(若是不存在這樣的數,也輸出-1)。io

創建100000個二進制Trie,第i個Trie中存儲i的全部倍數。class

查詢的時候,在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;
}
相關文章
相關標籤/搜索