cf round 482D Kuro and GCD and XOR and SUM

题意:

开始有个空集合,现在有两种操作:

$(1,x)$:给集合加一个数$x$,$x \leq 10^5$;

$(2,x,k,s)$:在集合中找一个$a$,满足$a \leq s-x$,而且$k|gcd(a,x)$;现在需要找满足条件的$a$,它异或$x$的值最大。$x,k,s \leq 10^5$

操作数$q \leq 10^5$

这道题就是看你想到一个算法有没有去算算实际复杂度

我们发现,对于所有在$[1,10^5]$的$i$,$10^5$之内的$i$的倍数的个数和,并不是很大,只有$2*10^7$左右

然后就维护$10^5$个trie就好了……

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=2e5+7,maxm=2e7+7,W=1e5,U=16,INF=0x3f3f3f3f;
int n,root[maxn],tot=W;
int son[maxm][2],minnum[maxm];
bool vis[maxn];

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int prime[maxn],totp,num[maxn];
bool ok[maxn];
void get_p() {
	For(i,2,W) {
		if(!ok[i]) prime[++totp]=i,num[i]=i;
		For(j,1,totp) {
			if(prime[j]>W/i) break;
			ok[i*prime[j]]=1;
			num[i*prime[j]]=prime[j];
			if(i%prime[j]==0) break;
		}
	}
}

void add(int pos,int x) {
	minnum[pos]=min(minnum[pos],x);
	int r;
	Rep(i,U,0) {
		r=(x>>i)&1;
		if(!son[pos][r]) minnum[son[pos][r]=++tot]=x;
		pos=son[pos][r]; minnum[pos]=min(minnum[pos],x);
	}
} 

int zz[maxn];
void get_add(int x) {
	if(vis[x]) return; vis[x]=1;
	int s=1,t=1,p,now,y,o=x; zz[1]=1;
	while(x!=1) {
		p=num[x]; now=0; y=1;
		while(x%p==0) x/=p,now++;
		For(i,1,now) {
			y*=p;
			For(j,1,s) zz[++t]=zz[j]*y;
		}
		s=t;
	}
	For(i,1,t) add(zz[i],o);
}

int get_ans(int x,int pos,int v) {
	if(x%pos||minnum[pos]>v) return -1;
	int r;
	Rep(i,U,0) {
		r=(x>>i)&1;
		if(minnum[son[pos][r^1]]<=v) pos=son[pos][r^1];
		else pos=son[pos][r];
	}
	return minnum[pos];
}

int main() {
	read(n); int op,k,x,v;
	get_p();
	For(i,0,W) minnum[i]=INF;
	For(i,1,n) {
		read(op); read(x);
		if(op==1) get_add(x);
		else {
			read(k); read(v);
			printf("%d\n",get_ans(x,k,v-x));
		}
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Serene-shixinyi/p/9092812.html