题解:
对于每个值先找到所有的因子。
然后每次add的时候,在他的所有因子都加入这个数。
然后询问的时候询问这个数的因子所构成的字典树。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int INF = 0x3f3f3f3f; const LL mod = 1e9+7; const int N = 1e5+10; vector<int> son[N]; struct Node{ int Min; Node * p[2]; Node(){ Min = INF; p[0] = p[1] = nullptr; } }*rt[N]; bool vis[N]; void init(){ for(int i = 1; i < N; i++){ rt[i] = new Node(); for(int j = i; j < N; j+=i){ son[j].pb(i); } } } void Add(int k, int u){ Node *tmp = rt[k]; tmp -> Min = min(tmp -> Min, u); for(int i = 18; i >= 0; i--){ int id = u>>i & 1; if(tmp -> p[id] == nullptr) tmp -> p[id] = new Node(); tmp = tmp -> p[id]; tmp -> Min = min(tmp -> Min, u); } } int Query(int x, int k, int s){ Node *tmp = rt[k]; if(x%k != 0 || tmp->Min+x > s) return -1; int ret = 0; for(int i = 18; i >= 0; i--){ int id = x >> i & 1; if(tmp -> p[id^1] != nullptr && tmp -> p[id^1] -> Min + x <= s){ tmp = tmp -> p[id^1]; ret += (id^1) << i; } else { tmp = tmp -> p[id]; ret += id << i; } } return ret; } int main(){ init(); int q, t, u, x, s, k; scanf("%d", &q); while(q--){ scanf("%d", &t); if(t == 1){ scanf("%d", &u); if(!vis[u]){ vis[u] = 1; for(int k : son[u]){ Add(k, u); } } } else{ scanf("%d%d%d", &x, &k, &s); printf("%d ", Query(x,k,s)); } } } return 0;