[GCD] 最小LCM

题目:

给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 << '
';

    return 0;
}
原文地址:https://www.cnblogs.com/zeolim/p/12270375.html