题目:
给n个数, 你需要找两个数使得LCM最小, 将两个数的位置输出
解题思路:
题目时间给了四秒, 数据范围 1e7
所以暴力是可以过的
尝试使用枚举范围内所有 gcd 解决问题
对于每个gcd x 有任意 gcd(n * x, m * x) = x
用 O nsqrt(n) 的筛法可以枚举出当前gcd = x下 最小的两个数组中含有的数字并计算结果
且这两个数字必定是当前gcd = x下最优解 所以可以玄学剪枝一下
/*
Zeolim - An AC a day keeps the bug away
*/
//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int INF = 0x3f3f3f3f;
const int MAXN = 1e7 + 10;
const ll MOD = 1e9 + 7;
ll pos[MAXN] = {0};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
int n;
cin >> n;
ll ans = ll(1) << 50, anspa = 1, anspb = 2;
for(ll i = 1, x; i <= n; ++i)
{
cin >> x;
if(pos[x] && x < ans)
{
ans = x;
anspa = pos[x], anspb = i;
}
else
{
pos[x] = i;
}
}
for(int i = 1; i < MAXN; ++i)
{
ll rpa = 0, rnuma = 0, rpb = 0;
for(int j = i; j < MAXN; j += i)
{
if(!rpa && !rpb && pos[j])
rpa = pos[j], rnuma = j;
else if(rpa && pos[j])
{
rpb = pos[j];
ll rans = rnuma * j / i;
if(rans < ans)
{
ans = rans, anspa = rpa, anspb = rpb;
}
break;
}
}
}
if(anspa > anspb)
swap(anspa, anspb);
cout << anspa << ' ' << anspb << '\n';
return 0;
}