【CodeForces - 1154G】Minimum Possible LCM(涉及数论很多东西。。)

You are given an array a consisting of n integers a1,a2,…,an.

Your problem is to find such pair of indices i,j (1≤i<j≤n) that lcm(ai,aj) is minimum possible.

lcm(x,y) is the least common multiple of x and y (minimum positive number such that both x and y are divisors of this number).

Input
The first line of the input contains one integer n (2≤n≤106) — the number of elements in a.

The second line of the input contains n integers a1,a2,…,an (1≤ai≤107), where ai is the i-th element of a.

Output
Print two integers i and j (1≤i<j≤n) such that the value of lcm(ai,aj) is minimum among all valid pairs i,j. If there are multiple answers, you can print any.

Examples
Input
5
2 4 8 3 6
Output
1 2
Input
5
5 2 11 3 7
Output
2 4
Input
6
2 5 10 1 10 2
Output
1 4
新的唯一分解的技巧,如果最大数据不大,可以预处理一下每个数的最小质因子,这个用欧拉线性筛处理,然后就可以从原来的 n \sqrt n n 优化到 l o g n logn logn,怪不得我总是超时,,,其实我也想到如果每次去枚举一个数的因子会超时,所以我一次性把 1 0 7 10^7 107范围内的每个数的因子都提前预处理,但是仍然超时,这样做一个时间复杂度高,空间复杂度也很大。
代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#define INF 0x7f7f7f7f
#define maxx 10000005
#define mod 1000000007
using namespace std;
typedef long long ll;
int pr[666000],cnt;
int P[maxx];
int a[maxx];
int n;
void init()
{
    P[0]=P[1]=1;
    for(int i=2;i<maxx;i++)
    {
        if(P[i]==0)
        {
            pr[++cnt]=i;
            P[i]=i;
        }
        for(int j=1;j<=cnt&&pr[j]<=P[i];j++)
        {
            if((ll)i*pr[j]>=maxx)break;
            P[i*pr[j]]=pr[j];
        }
    }
}
int min1[maxx];
int min2[maxx];
inline void update(int factor,int ind)
{
    if(a[min1[factor]]>a[ind])
    {
        min2[factor]=min1[factor];
        min1[factor]=ind;
    }
    else if(a[min2[factor]]>a[ind])
    {
        min2[factor]=ind;
    }
}
int fac[100];
int e[100];
int tot;
int getFac(int x)
{
    tot=0;
    while(x!=1)
    {
        int now=P[x];
        fac[++tot]=now;
        e[tot]=0;
        while(x%now==0)
        {
            e[tot]++;
            x/=now;
        }
    }
}
int index;
void dfs(int cur,int res)
{
    if(cur>tot)
    {
        //cout<<res<<endl;
        update(res,index);
        return;
    }
    dfs(cur+1,res);
    for(int i=1;i<=e[cur];i++)
    {
        res*=fac[cur];
        dfs(cur+1,res);
    }
}
int main()
{
    init();
    cin>>n;
    bool sign=false;
    int _min=INF;
    int N=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",a+i);
        N=max(N,a[i]);
        if(a[i]>1)
        {
            _min=min(_min,a[i]);
        }
        else
        {
            if(!sign)
                sign=true;
            else _min=1;
        }
    }
    if(sign)
    {
        int ind;
        for(int i=1;i<=n;i++)
            if(a[i]==1)
        {
            ind=i;
            break;
        }
        int ind2;
        for(int i=1;i<=n;i++)
        {
            if(i!=ind&&a[i]==_min)
            {
                ind2=i;
                break;
            }
        }
        if(ind>ind2)swap(ind,ind2);
        cout<<ind<<" "<<ind2<<endl;
    }
    else
    {
        a[0]=INF;
        for(int i=1;i<=n;i++)
        {
            getFac(a[i]);
            index=i;
            dfs(1,1);
        }
        int ind;
        ll lcm=1e15;
        for(int i=1;i<=N;i++)
        {
            if(a[min1[i]]!=INF&&a[min2[i]]!=INF)
            {
                if(lcm>(ll)a[min1[i]]*a[min2[i]]/i)
                {
                    ind=i;
                    lcm=(ll)a[min1[i]]*a[min2[i]]/i;
                }
            }
        }
        //for(int i=1;i<=N;i++)
        //{
        //    cout<<i<<": "<<a[min1[i]]<<" "<<a[min2[i]]<<endl;
        //}
        if(min1[ind]>min2[ind])swap(min1[ind],min2[ind]);
        cout<<min1[ind]<<" "<<min2[ind]<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值