Generalización:
Se nos da un número [math] n \ in \ mathbb {N} [/ math], representado en la base [math] b \ in \ mathbb {N} \ backslash \ {1 \} [/ math]. Deseamos encontrar eficientemente el número de instancias de dígitos [math] d \ in \ mathbb {N} [/ math] (donde [math] d \ leq b-1 [/ math]) al escribir (en base [math ] b [/ math]) todos los números naturales desde [math] 1 [/ math] hasta [math] n [/ math], inclusive.
Para nuestra pregunta específica, [matemáticas] b = 10 [/ matemáticas] y [matemáticas] d = 1 [/ matemáticas]. Por lo tanto, deseamos encontrar el número de instancias de dígitos [matemática] 1 [/ matemática] al escribir (en base [matemática] 10 [/ matemática]) todos los números naturales desde [matemática] 1 [/ matemática] hasta [matemática ] n [/ math], inclusive.
- Cómo aprender estructuras de datos usando C ++ de manera simple
- ¿Qué problema exacto está resolviendo el 'comercio conversacional'?
- ¿Cuál es el algoritmo detrás de la creación de una nueva fuente que solo muestra publicaciones de tus seguidores?
- En file.log, cada línea comienza con una marca de fecha completa. ¿Qué comando podría usarse para devolverme las líneas N-1, N y N + 1 con una diferencia de tiempo mayor que X segundos entre N y N + 1?
- Si creció en una familia alcohólica, ¿cuál fue su historia y los desafíos que enfrenta personal y profesionalmente debido a la educación?
Responder:
El número de instancias de dígitos [matemática] d [/ matemática] al escribir todos los números de [matemática] 1 [/ matemática] a [matemática] n [/ matemática] en base [matemática] b [/ matemática] es [matemática ] \ boxed {\ sum \ limits_ {i = 0} ^ {\ lfloor \ log_ {b} {(n + 1)} \ rfloor} {[n_iib ^ {i-1} + ((n + 1) \ mod {b ^ i}) 1_ {n_i = d} + (b ^ i) 1_ {n_i> d}]}} [/ math], donde [math] n_i = \ lfloor \ frac {n + 1} {b ^ i} \ rfloor \ mod {b} [/ math] y [math] 1_x = \ begin {cases} 1 & \ text {,} x \ text {es verdadero} \\ 0 & \ text {, de lo contrario} \ end {casos} [/ matemáticas].
Para nuestra pregunta específica, el número de instancias del dígito [matemático] 1 [/ matemático] al escribir todos los números desde [matemático] 1 [/ matemático] hasta [matemático] n [/ matemático] en base [matemático] 10 [/ matemática] es [matemática] \ sum \ limits_ {i = 0} ^ {\ lfloor \ log_ {10} {(n + 1)} \ rfloor} {[n_ii10 ^ {i-1} + ((n + 1) \ mod {10 ^ i}) 1_ {n_i = 1} + (10 ^ i) 1_ {n_i> 1}]} [/ matemática], donde [matemática] n_i = \ lfloor \ frac {n + 1} {10 ^ i} \ rfloor \ mod {10} [/ math].
Por ejemplo, podemos calcular el número de instancias del dígito [math] 1 [/ math] al escribir todos los números desde [math] 1 [/ math] hasta [math] 30112 [/ math] en base [math] 10 [ /mates]. Primero, tenga en cuenta que [matemática] n_0 = 3 [/ matemática], [matemática] n_1 = 1 [/ matemática], [matemática] n_2 = 1 [/ matemática], [matemática] n_3 = 0 [/ matemática] y [ matemáticas] n_4 = 3 [/ matemáticas]. Por lo tanto, la respuesta es [matemáticas] [3 (0) (10 ^ {0-1}) + 10 ^ {0}] + [1 (1) (10 ^ {1-1}) + ((30112 + 1 ) \ mod {10 ^ {1}})] + [1 (2) (10 ^ {2-1}) + ((30112 + 1) \ mod {10 ^ 2})] + [0 (3) ( 10 ^ {3-1})] + [3 (4) (10 ^ {4-1}) + 10 ^ {4}] = 22038 [/ matemáticas].
Razonamiento:
Primero, notamos que el número de instancias de un dígito distinto de cero [matemática] d [/ matemática] en los números de [matemática] 0 [/ matemática] a [matemática] b ^ {i} -1 [/ matemática] es [matemáticas] ib ^ {i-1} [/ matemáticas]. Esto se debe a que cada uno de estos números puede representarse de manera única con dígitos [matemáticos] i [/ matemáticos], por lo que hay dígitos totales [matemáticos] ib ^ i [/ matemáticos]. Dado que cada dígito se distribuye uniformemente sobre estos, hay [math] \ frac {ib ^ i} {b} = ib ^ {i-1} [/ math] instancias de un solo dígito.
Entonces multiplicamos [math] ib ^ {i-1} [/ math] por [math] n_i [/ math] (que es el dígito en el lugar [math] i ^ {th} [/ math] de [math] n [/ math] (lectura de derecha a izquierda)) para tener en cuenta el número de dígitos [math] d [/ math] en todos los números desde [math] 1 [/ math] hasta [math] n_ib ^ {\ lfloor \ log_ {b} {n} \ rfloor} [/ math].
A continuación, debemos tener en cuenta todas las instancias de [math] d [/ math] en el dígito más significativo de la potencia actual [math] i [/ math]. Si [math] n_i> d [/ math], obtendríamos [math] b ^ i [/ math] instancias adicionales de [math] d [/ math] de números anteriores. Pero si [math] n_i = d [/ math], entonces solo obtendríamos [math] n \ mod {b ^ i} [/ math] instancias adicionales de [math] d [/ math].
Finalmente, tomamos todas las ideas anteriores y las aplicamos para cada potencia [matemática] i [/ matemática] desde [matemática] 0 [/ matemática] hasta [matemática] \ lfloor \ log_b {(n + 1)} \ rfloor [/ matemática] (es decir, para cada dígito de [matemática] n [/ matemática]). Esto nos da nuestra respuesta final.
Código:
Este script de Python calcula eficientemente el valor en tiempo de ejecución [matemático] O (\ log {n}) [/ matemático], comprobando contra la ingenua implementación simulateF (que es [matemático] O (n \ log {n}) [/ matemático] tiempo de ejecución). Específicamente, la función computeStrF es incluso más rápida que computeF, pero computeStrF solo es compatible con [math] b = 10 [/ math].
#! / usr / bin / python
matemáticas de importación
def main ():
# print “d \ tn \ tsim”
ds = [1, 9]
para d en ds:
para n en rango (1, 10000):
sim = simulateF (n, d)
comp = computeF (n, d, 10)
compStr = computeStrF (n, d)
afirmar compStr == sim
afirmar comp == sim
# imprimir str (d) + “\ t” + str (n) + “\ t” + str (sim)
def simulateF (n, d):
toReturn = 0
strD = str (d)
para i en rango (1, n + 1):
strI = str (i)
para c en strI:
si c == strD:
toReturn + = 1
volver a Regresar
def computeF (n, d, b):
n + = 1
toReturn = 0
bPow = 1
si b == 10:
a = int (math.floor (math.log10 (n)))
más:
# Python tiene un error de redondeo, por lo que
# a = 3 cuando n = 1000 yb = 10 (mientras que debería ser 4).
a = int (math.floor (math.log (n) / math.log (b)))
para i en rango (a + 1):
n_i = math.floor (n / bPow)% b
toReturn + = n_i * i * bPow / b
si n_i == d:
toReturn + = n% bPow
elif n_i> d:
toReturn + = bPow
bPow * = b
volver a Regresar
def computeStrF (n, d):
n + = 1
strN = str (n)
toReturn = 0
bPow = 1
longitud = len (strN)
para i en rango (longitud):
n_i = int (strN [longitud – i – 1])
toReturn + = n_i * i * bPow / 10
si n_i == d:
toReturn + = n% bPow
elif n_i> d:
toReturn + = bPow
bPow * = 10
volver a Regresar
if __name__ == ‘__main__’:
principal()