"Concurso de algoritmos · 300 preguntas rápidas" Una pregunta por día: "Mínimo común múltiplo"

" Competencia de algoritmos: 300 preguntas rápidas " se publicará en 2024 y es un libro de ejercicios auxiliar para la "Competencia de algoritmos" .
Todas las preguntas se colocan en el nuevo juez en línea del DO de creación propia .
Los códigos se proporcionan en tres lenguajes: C/C++, Java y Python. Los temas son principalmente temas de nivel medio a bajo y son adecuados para estudiantes principiantes y avanzados.


" Mínimo común múltiplo ", enlace: http://oj.ecustacm.cn/problem.php?id=1820

Descripción de la pregunta

[Descripción del problema] Dado un número n, pregunte si existe un intervalo l, r tal que n sea igual al mínimo común múltiplo de todos los números en todo el intervalo.
[Formato de entrada] La primera línea es un número entero positivo T, lo que indica que hay T conjuntos de datos de prueba, 1≤T≤10000.
   Para cada conjunto de datos de prueba, ingrese un número entero que represente el número n, 1≤n≤10^18.
[Formato de salida] Para cada conjunto de datos de prueba, si hay un intervalo [l, r] como respuesta, entonces genere dos números ly r.
   Si hay varios conjuntos de soluciones, genere la solución con la l más pequeña. Si todavía hay varias soluciones y l es el mismo, se genera la solución con la r más pequeña.
   Si no hay solución, genera -1.
【Muestra de entrada】

3
12
504
17

【Muestra de salida】

1 4
6 9
-1

respuesta

   Si calcula directamente [L, R] correspondiente a n, solo puede buscar violentamente todas las combinaciones posibles, lo que requiere una gran cantidad de cálculos. Es fácil pensar en un método más simple: haga el cálculo inverso, primero precalcule todos los n correspondientes a [L, R] y luego consulte el [L, R] correspondiente para la entrada n.
   Pero al atravesar directamente todos [L, R], la cantidad de cálculo sigue siendo muy grande. El valor máximo posible de L y R es n ≤ 1 0 18 = 1 0 9 \sqrt{n}≤ \sqrt{10^{18}}=10^9norte 1 018 =1 09 . Recorra todos L y R, la cantidad de cálculoes O ( nn ) = O ( n ) O(\sqrt{n}\sqrt{n}) = O(n)Oh (norte norte )=O ( n ) , tiempo de espera.
   Si hay al menos 3 números en [L, R], es decir, al menos [L, L+1, L+2], entonces el valor máximo de L es n 3 ≤ 1 0 6 \sqrt[3 ]{ norte} ≤ 10 ^63norte 1 06 , la cantidad de cálculo se reduce considerablemente.
   En cuanto al intervalo [L, L+1] que contiene solo 2 números, se puede verificar por separado y la cantidad de cálculo es muy pequeña. Ingrese un valor de n y verifique quenn + 1 = n \sqrt{n}\sqrt{n+1}=nnorte norte+1 =Sólo importa si n está establecido.
[Punto clave]GCD.

código C ++

   Utilice el mapa para almacenar los resultados del cálculo. La respuesta correspondiente a n es [L, R] que se almacena en el mapa por primera vez.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
map<ll, pair<int,int>>ans;
void init(){
    
            //预处理,ans[n]表示n对应的答案[L,R],区间内至少3个数
    for(ll L = 1; L <= 2000000; L++)   {
    
    
        ll n = L * (L + 1);
        for(ll R = L + 2; ;R++)   {
    
    
            ll g = __gcd(n, R);
            if(n / g > INF / R)    break;
            n = n / g * R;           //先除再乘,防止溢出
            if(!ans.count(n))        //res这个数还没有算过,存起来
                ans[n] = make_pair(L, R);
        }
    }
}
int main(){
    
    
    init();
    int T;  scanf("%d",&T);
    while(T--) {
    
    
        ll n;  scanf("%lld",&n);
        //先特判区间长度为2的情况: [L,L+1]
        ll sqrt_n = sqrt(n + 0.5);
        pair<int,int>res;
        if(sqrt_n * (sqrt_n + 1) == n)   {
    
    
            res = make_pair(sqrt_n, sqrt_n + 1);
            if(ans.count(n))
                if(res.first > ans[n].first)
                    res = ans[n];
        }
        else if(ans.count(n)) res = ans[n];
        else {
    
     puts("-1"); continue; }
        printf("%d %d\n", res.first, res.second);
    }
    return 0;
}

código java

import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;
class Main{
    
    
    static class Pair<T1, T2> {
    
    
        public T1 first;
        public T2 second;
        public Pair(T1 first, T2 second) {
    
    
            this.first = first;
            this.second = second;
        }
    }

    static final long INF = 1000000000000000000L;
    static Map<Long, Pair<Integer,Integer>> ans;
    static void init() {
    
    
        ans = new HashMap<>();
        for (long L = 1; L <= 2000000; L++) {
    
    
            long n = L * (L + 1);
            for (long R = L + 2; ; R++) {
    
    
                long g = gcd(n, R);
                if (n / g > INF / R) break;
                n = n / g * R;
                if (!ans.containsKey(n)) 
                    ans.put(n, new Pair<Integer,Integer>((int)L, (int)R));
            }
        }
    }
    static long gcd(long a, long b) {
    
     return b == 0 ? a : gcd(b, a % b);}
    public static void main (String[] args) throws java.lang.Exception  {
    
    
        init();
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while (T-- > 0) {
    
    
            long n = sc.nextLong();
            long sqrt_n = (long)Math.sqrt(n + 0.5);
            Pair<Integer,Integer> res;
            if (sqrt_n * (sqrt_n + 1) == n) {
    
    
                res = new Pair<Integer,Integer>((int)sqrt_n, (int)(sqrt_n + 1));
                if (ans.containsKey(n)) {
    
    
                    if (res.first > ans.get(n).first)  res = ans.get(n);
                }
            } else {
    
    
                if (ans.containsKey(n)) res = ans.get(n);
                else {
    
    
                    System.out.println("-1");
                    continue;
                }
            }
            System.out.println(res.first + " " + res.second);
        }
    }
}

código pitón

   Utilice un diccionario para almacenar los resultados del cálculo y la respuesta correspondiente a n es [L, R] almacenada en el diccionario por primera vez.

 import math
INF = 10**18
ans = {
    
    }
def init():
    global ans
    for L in range(1, 2000000+1):
        n = L * (L + 1)
        R = L + 2
        while True:
            g = math.gcd(n, R)
            if n // g > INF // R: break
            n = n // g * R
            if n not in ans:   ans[n] = (L, R)
            R += 1
init()
T = int(input())
for _ in range(T):
    n = int(input())
    sqrt_n = int(math.sqrt(n + 0.5))
    if sqrt_n * (sqrt_n + 1) == n:
        res = (sqrt_n, sqrt_n + 1)
        if n in ans:
            if res[0] > ans[n][0]:
                res = ans[n]
    else:
        if n in ans:   res = ans[n]
        else:
            print("-1")
            continue
    print(res[0], res[1])

Supongo que te gusta

Origin blog.csdn.net/weixin_43914593/article/details/132427970
Recomendado
Clasificación