E Max GCD
Endereço do título original:
https://ac.nowcoder.com/acm/contest/4090/E
Idéia de solução de problemas: não importa o que seja t, é encontrar um k no intervalo de [l, r] para que o maior divisor comum de a [k] e x seja o maior.
Portanto, precisamos armazenar apenas o divisor de cada a [i] e seu índice correspondente (i), vec [divisor (a [i])] .push_back (i) e depois enumerar os divisores de x de grande para pequeno, à direita Cada divisor de x é pesquisado em binário no vec correspondente para saber se existe um índice no intervalo [l, r]. Se existir, o divisor correspondente é a resposta.
Código de referência:
#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;
}