es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Función de c# que acepta un número entero n y devuelve el número más bajo que puede ser dividido por los números divisores 1..n.

Necesito escribir una función que tome como argumento un número n y devuelva (como cadena) el número más pequeño posible que pueda ser divisible uniformemente por todos los números del 1 al n. Por ejemplo, si n = 4, la función devolverá 12 porque 12/4 12/3 12/2 12/1 son números enteros.

He escrito una función para eso que funciona bien cuando los números son menores que 19. Sin embargo, por encima de 19, el tiempo de cálculo aumenta significativamente. ¿Alguien puede darme una pista de cómo mejorar el mecanismo de esta función para hacerlo más rápido?

public static string Smallest(int n)
{
    int good = 0; //mantendrá el número de veces que se dividió sin resto
    int num = n; //el número más pequeño posible es n
    while (true)
    {
        good = 0;
        for (int i = n; i >= 1; i--)
        {
            if (num % i == 0) good++; //si obtenemos un resto igual a cero, significa que no hay resto para la división
            if (good == n) return num.ToString(); //si se obtiene cero resto n veces, se devolverá el número
        }
        num++;
    }
}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    En primer lugar, es genial que ya haya creado una función que funciona efectivamente para números más pequeños.

    Un enfoque para mejorar el rendimiento de la función es usar la factorización de números primos. El mínimo común múltiplo de un conjunto de números se puede encontrar utilizando su factorización en números primos.

    Por ejemplo, si n=4, los números son 1, 2, 3 y 4. La factorización en números primos de cada número es:

    1 = 1
    2 = 2
    3 = 3
    4 = 2^2

    Los números 2 y 3 solo aparecen una vez en la factorización en números primos, mientras que 2 aparece dos veces. Por lo tanto, solo necesitamos multiplicar 2 y 3, y 2 dos veces para obtener el mínimo común múltiplo de 1, 2, 3 y 4, que es 12.

    Este enfoque puede mejorar significativamente el rendimiento de la función, especialmente para números más grandes, porque calcular la factorización en números primos de un número es mucho más rápido que hacer un bucle a través de todos los números de 1 a n para verificar si hay una división par.

    Aquí hay una función actualizada que utiliza este enfoque:

    public static string Smallest(int n)
    {
        int[] primes = GetPrimes(n);
        int[] powers = new int[primes.Length];
    
        for (int i = 1; i <= n; i++)
        {
            int[] factorization = GetPrimeFactorization(i, primes);
            for (int j = 0; j < primes.Length; j++)
            {
                if (factorization[j] > powers[j])
                {
                    powers[j] = factorization[j];
                }
            }
        }
    
        int result = 1;
        for (int i = 0; i < primes.Length; i++)
        {
            result *= (int)Math.Pow(primes[i], powers[i]);
        }
    
        return result.ToString();
    }
    
    private static int[] GetPrimes(int n)
    {
        bool[] isPrime = new bool[n + 1];
        for (int i = 2; i <= n; i++)
        {
            isPrime[i] = true;
        }
    
        for (int i = 2; i * i <= n; i++)
        {
            if (isPrime[i])
            {
                for (int j = i * i; j <= n; j += i)
                {
                    isPrime[j] = false;
                }
            }
        }
    
        int count = 0;
        for (int i = 2; i <= n; i++)
        {
            if (isPrime[i])
            {
                count++;
            }
        }
    
        int[] primes = new int[count];
        int index = 0;
        for (int i = 2; i <= n; i++)
        {
            if (isPrime[i])
            {
                primes[index] = i;
                index++;
            }
        }
    
        return primes;
    }
    
    private static int[] GetPrimeFactorization(int n, int[] primes)
    {
        int[] factorization = new int[primes.Length];
    
        for (int i = 0; i < primes.Length; i++)
        {
            int prime = primes[i];
            int count = 0;
            while (n % prime == 0)
            {
                count++;
                n /= prime;
            }
            factorization[i] = count;
        }
    
        return factorization;
    }
    

    Esta función primero calcula todos los números primos hasta n utilizando el algoritmo de la Criba de Eratóstenes. Luego, hace un bucle a través de todos los números de 1 a n y calcula su factorización en números primos utilizando la matriz de números primos.

    La matriz de potencias realiza un seguimiento de la potencia máxima de cada número primo que aparece en la factorización en números primos de cualquiera de los números de 1 a n. Una vez que se han calculado todas las factorizaciones en números primos, se construye el mínimo común múltiplo multiplicando cada número primo a su potencia correspondiente.

    En general, este enfoque debería ser mucho más rápido que el bucle a través de todos los números de 1 a n, especialmente para valores más grandes de n.

Comments are closed.