Codeforces Round #552 (Div. 3) G.Minimum Possible LCM(数论-埃筛+枚举gcd)

题目

给你n(2<=n<=1e6)个数,1<=ai<=1e7

要求输出两个下标i和j,使得lcm(ai,aj)最小,

多解时,输出任意两个即可,但要保证i<j

思路来源

dreamoon巨神的CF代码

题解

首先,将每个出现的位置记在pos[]数组里,

考虑到,存在lcm(x,x)==x的情形,在读入的时候特判一下

再考虑到,lcm(x,y)==x*y/gcd(x,y)

枚举i==gcd(x,y),对于每个i,

找到其倍数里出现的最小的两个x、y,

这个是埃筛的操作,j+=i的时候会遍历到i的倍数,

取到两个就break就好,毕竟更大的x、y,

对于固定下来的gcd来讲,答案不会更优

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> 
using namespace std;
typedef long long ll;
const int maxn=1e7+10;
int n,v;
int pos[maxn];//每个值出现的位置
ll ans;
int ai,aj; 
int main()
{
	scanf("%d",&n);
	ans=1e18;
	for(int i=1;i<=n;++i)
	{
		scanf("%d",&v);
		if(pos[v]&&ans>v)
		ans=v,ai=pos[v],aj=i;
		pos[v]=i;
	}
	for(ll i=1;i<maxn;++i)
	{
		ll first=-1;
		for(ll j=i;j<maxn;j+=i)
		{
			if(pos[j])
			{
				if(first==-1)first=j;//第一个值ai 
				else //第二个值aj 
				{
				   if(ans>first*j/i)
		           ans=first*j/i,ai=pos[first],aj=pos[j];
				   break;//找到最小的两个 满足gcd(ai,aj)==i; 
				}
			}
		}
	}
	if(ai>aj)swap(ai,aj);
	printf("%d %d\n",ai,aj);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值