E Max GCD
Adresse originale du titre:
https://ac.nowcoder.com/acm/contest/4090/E
Idée de résolution de problèmes: quels que soient s et t, il s'agit de trouver un k dans la gamme de [l, r] de sorte que le plus grand diviseur commun de a [k] et x soit le plus grand.
Il nous suffit donc de stocker le diviseur de chaque a [i] et son index correspondant (i), vec [diviseur (a [i])] .push_back (i) , puis d'énumérer les diviseurs de x de grand à petit, à droite Chaque diviseur de x est recherché binaire dans le vec correspondant pour savoir s'il existe un index dans la plage [l, r]. S'il existe, alors le diviseur correspondant est la réponse.
Code de référence:
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define ll long long
#define INF 0x3f3f3f3f
const int maxn = 1e5 + 10;
int n,q,a[maxn];
vector<int> vec[maxn];
void divisor(int x,int id){
for(int i = 1 ; i * i <= x ; i++) {
if (x % i == 0) {
vec[i].push_back(id);
if (x / i != i) vec[x / i].push_back(id);
}
}
}
int solve(int l,int r,int x){
for(int i = 1 ; i * i <= x ; i++) if(x % i == 0){
int j = x / i;
int pos = lower_bound(vec[j].begin(),vec[j].end(),l) - vec[j].begin();
if(pos < vec[j].size() && vec[j][pos] >= l && vec[j][pos] <= r) return j;
}
for(int i = sqrt(x) ; i >= 1 ; i--) if(x % i == 0){
int j = i;
int pos = lower_bound(vec[j].begin(),vec[j].end(),l) - vec[j].begin();
if(pos < vec[j].size() && vec[j][pos] >= l && vec[j][pos] <= r) return j;
}
}
signed main() {
IO;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
divisor(a[i], i);
}
while (q-- > 0) {
int l, r, x;
cin >> l >> r >> x;
cout << solve(l, r, x) << endl;
}
return 0;
}