Codeforces B.可能な最小LCM(貪欲の数論)

件名の説明:

B.可能な最小LCM

テストあたりの時間制限

4秒

テストごとのメモリ制限

1024メガバイト

入力

標準入力

出力

標準出力

あなたは配列を指定された整数からなる1、...、* ** N * 2を、

問題は、インデックスのようなペアを見つけることであるIJ 、LのCの M\(a_iを\) \(a_j \) の可能な最小値です。

リットルのC MXYは)の最小公倍数であり、XおよびY(両方ように最小の正の数のx及びyはこの数の約数です)。

入力

入力の最初の行は1つの整数含まNを -の要素数

入力の2行目は含まれ、n個の整数のA1、A2、...、(1≤ai≤107)、AIはa.isのi番目の要素であるIを

出力

2つの整数を印刷し、私と(1≤ 私は < Jの ≤のnは、有効なすべてのペアの中で最小であるIJ

アイデア:

2つの数の最小公倍数の数字の名称必要最小限のセット。簡単なアイデアの始まりはGCDごとに2つの数、各需要に応じて2つの数の最小公倍数最大公約数を見つけるために、列挙することです。このアプローチの時の複雑さO(ある\(N-2 ^ \ N-log_2 \) )、4 秒を限定、科学的ではない明らかに、対象データ範囲を調べ、\(^ {10} 12 log_210ある。6 ^ { } \) 遠くまでとなります。方法は?

のが一般的考えようLCMのに問題GCDの問題がリンクされています。データの範囲が与えられているので、検索する方法を、多くの要因が、1から開始する、列挙を考慮する\ [10 ^ 7 \] 回答の列数の最大公約数の最小数の2倍を見つけます。なぜ?

今共通因子dを列挙するとし、列の数がdの倍数であり、\を(X_1 \) < \(X_2 \) < \(X_3 \) <... < \(x_nに関する\) dがある場合は、\( X_1 \) \(X_2 \) GCDの、それが最小の状態、X1、X2確か最小公倍数を(D因子である場合)を満たします。dは、X1、X2 GCDのではない場合、背後に、その後、最大値は最小の公倍数ではないでしょうGCDの数ではありませんでした。

Dの条件が、最適解が確かに局所的である場合、Dので、小から大規模な列挙です。あなたが満たされていない場合dはGCDされ、D ++、満足するまで列挙を続けます。アルゴリズムは終了しますので、アルゴリズムの保証正しさがあります。アルゴリズムの複雑さはO(\(N \ N-log_2 \)

ケースの重複する要素が存在する場合、これは、要素自体の最小公倍数であるが、ときに最小の要素が繰り返しエレメントよりも大きい場合、LCMは、それが大域的最小ではないであろうよりも大きくなければならないのでだけ、繰り返すことができることに注意してくださいLCMは、連続的最小を残すために、入力時に個体を覆います。

LLONG_MAXに注意し、LONG_MAXは、元の数が十分でないので、私は、間違って開始し、同じではありません。

コード:

#include <iostream>
#include <climits>
#define INF LLONG_MAX
#define max_n 10000007
using namespace std;
long long a[max_n];
int n;
int pos[max_n];
long long ans = 0;
long long minm = INF;
int x = 0;
int y = 0;
long long gcd(long long a,long long b)
{
    return (b==0)?a:gcd(b,a%b);
}
int main()
{
    cin >> n;
    for(int i = 1;i<=n;i++)
    {
        int v;
        cin >> v;
        a[v]++;
        if(a[v]>1&&v<minm)
        {
            minm = v;
            x = pos[v];
            y = i;
        }
        pos[v] = i;
    }
    for(int i = 1;i<max_n;i++)
    {
        long long v = 0;
        for(int j = i;j<max_n;j+=i)
        {
            if(a[j]==0)
            {
                continue;
            }
            if(v==0)
            {
                v = j;
            }
            else
            {
                long long g = gcd(v/i,j/i);
                if(g==1)
                {
                    ans = (long long)j/i*v;
                    if(ans<minm)
                    {
                        //cout << "v " << v << " j " << j << endl;
                        minm = ans;
                        x = pos[v];
                        y = pos[j];
                    }
                }
                break;

            }
        }
    }
    if(x>y) swap(x,y);
    cout << x <<  " " << y << endl;
    return 0;
}

参考記事:

KobeDuu、可能な最小LCM【枚举】、https://blog.csdn.net/qq_41157137/article/details/89353527

おすすめ

転載: www.cnblogs.com/zhanhonhao/p/11260616.html