Anillo Joseph Blue Bridge Cup (recursividad)

1. Descripción del problema:

El número de n individuos es 1 ~ n, si están dispuestos en un círculo en el sentido de las agujas del reloj según el número, el número se informa en el sentido de las agujas del reloj de la persona con el número 1. (El número se informa desde 1) Cuando el número se informa a k, la persona se retirará del círculo de juego. La siguiente persona comienza a contar desde 1 nuevamente. Encuentra el número de la última persona que queda. Este es el famoso problema del anillo de Joseph. Esta pregunta es para encontrar el número de la última persona restante cuando se conocen n y k.

Ingrese descripción

La entrada es una línea con dos enteros separados por espacios n, k (0 <n, k <10 ^ 7)

Descripción de salida

Es necesario generar un número entero que represente el número de la última persona restante.

Entrada y salida de muestra

Entrada: 10 3

Salida: 4

Límite de funcionamiento
Tiempo de funcionamiento máximo: 1 s
Memoria de funcionamiento máxima: 256 M

2. Análisis de pensamiento:

① La forma más fácil de pensar al principio es el método de simulación. La programación simula todo el proceso para resolverlo. Siempre que haya más de 2 personas, se ejecuta el bucle. Se utiliza una variable en el bucle para contar y simular Sin embargo, debido a que la cantidad de datos es relativamente grande, cuando la cantidad de datos es grande, se agotará el tiempo de espera, por lo que no se puede resolver mediante simulación. De hecho, el anillo de Joseph es un problema matemático clásico. La descripción original es: N individuos están numerados 1, 2, ..., N, y los números se informan por turno. Cada vez que informe a M, mate a esa persona y pregunte por el número del ganador final. El problema del anillo de Joseph se puede resolver mediante derivación matemática. La respuesta se obtiene finalmente de la derivación de la fórmula paso a paso. Busqué información en Internet y descubrí que se puede resolver después de comprender la idea. Un ejemplo simple será más fácil de entender (usando un ejemplo de un tipo grande en el blog de csdn)

② Ejemplo: Hay un total de 11 personas con números 1, 2, 3 ... 11. Primero forman una fila. Suponiendo que todas las personas que reportan a 3 mueren, pregunte el número de la persona que no fue asesinada al final. .cuantos? La forma más fácil es primero enumerar una tabla que cambia dinámicamente para obtener el número del ganador. La siguiente es una tabla del proceso de derivación, y luego observar la relación entre el número del ganador en cada paso y el paso anterior.

Suponiendo que hay una función f (n, k), la función significa que actualmente hay n personas que informan el número, y el número del ganador cuando informa a k. De acuerdo con la fórmula anterior, esta fórmula se puede derivar: f (t , k) = (f (t-1, k) + k)% t, donde t es el número de individuos informado por t actualmente. En primer lugar, comience desde el primer informe, numerado del 1 al 11. Cuando se llama al número 3, la persona numerada 3 muere, y luego la persona numerada 4 comienza a informar el número del 1 ... Sí. Se encuentra que la persona después del número 4 avanzó 3 posiciones cuando reportó el número por segunda vez (el número 4 ocupa el primer lugar), y lo mismo es cierto para el último ejemplo, hasta el ganador final. Entonces, cuando solo hay una persona, entonces el número del ganador es 1 (correspondiente al subíndice 0) para que podamos comenzar con la persona cuyo subíndice final es 0 y avanzar un paso, y podemos encontrar que f (2 , 3) = (f (1, 3) + 3)% 2 (Actualmente hay dos personas), que en realidad es el proceso inverso en este momento. Para derivar hacia adelante (el número del ganador al principio), debe mover k posiciones hacia atrás, por lo que debe sumar 3 (se deduce restar 3 cuando solo hay un ganador), y actualmente hay k personas, por lo que mi subíndice no puede exceder k, por lo que necesito tomar el resto de k para indica que el ganador se mueve k retrocede Luego el subíndice debajo del número actual de personas, ... hasta que haya n personas, entonces se acabó. Así que solo deriva paso a paso en el ciclo.

En términos generales, es una cuestión de si avanzar o retroceder, lo que se puede entender observando la ley de movimiento de números anterior.

3. El código es el siguiente:

if __name__ == '__main__':
    # 本质上是移动了k个位置, 所以我们可以从最后胜利的那个人的下标0开始往上推导
    n, k = map(int, input().split())
    index = 0
    for i in range(2, n + 1):
        # 对i取余是上一步的情况下往后移动k个位置在目前i个人的真实编号
        index = (index + k) % i
    # 因为编号是从1开始的所以要返回index + 1
    print(index + 1)

 

Supongo que te gusta

Origin blog.csdn.net/qq_39445165/article/details/115199150
Recomendado
Clasificación