不大懂这个题怎么一群老哥跑的飞快/kk
异或最大值不难想到Trie,但是还有一个(gcd)的限制比较烦人,注意到(xleq 10^5)的(x)的因数个数不会太多,那么我们可以维护(10^5)个Trie,第(k)个表示所有的(k)的倍数的数组成的Trie,那么每次询问只需要询问第(k)个Trie即可,当然首先要保证(k|x)
还剩下一个(vleq s-x)的限制,这个比较轻松,对Trie树上的所有点记录下其子树中的最小值,如果子树的最小值都不满足这个限制就没有必要继续询问下去了
预处理(1- 10^5)中的所有数的所有因数,这个可以(O(nlogn))完成
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int ch[30002000][2],minx[30002000],root[100100],tot=0,val[30002000];
vector<int> fac[100100];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void insert(int &now,int x,int d)
{
if (!now) {now=(++tot);minx[now]=maxd;}
minx[now]=min(minx[now],x);
if (d<0) {val[now]=x;return;}
insert(ch[now][(x>>d)&1],x,d-1);
}
int query(int now,int lim,int x,int d)
{
if (d<0) return val[now];
int ch0=ch[now][0],ch1=ch[now][1];
if ((!ch0) || (minx[ch0]>lim)) return query(ch1,lim,x,d-1);
if ((!ch1) || (minx[ch1]>lim)) return query(ch0,lim,x,d-1);
return query(ch[now][((x>>d)&1)^1],lim,x,d-1);
}
int main()
{
rep(i,1,N)
for (int j=i;j<=N;j+=i) fac[j].pb(i);
int q=read();
while (q--)
{
int op=read();
if (op==1)
{
int x=read(),len=fac[x].size();
rep(i,0,len-1)
{
int y=fac[x][i];
insert(root[y],x,18);
}
}
else
{
int x=read(),k=read(),s=read();
if ((x%k) || (!minx[root[k]]) || (minx[root[k]]>s-x)) puts("-1");
else printf("%d
",query(root[k],s-x,x,18));
}
}
return 0;
}