J'ai besoin de trouver le chiffre unitaire de x1 ^ (x2 ^ (x3 ^ (... ^ xn)))
parmi les entiers passés dans la fonction sous forme de liste . Par exemple, l'entrée [3, 4, 2]
renverrait 1
car 3 ^ (4 ^ 2) = 3 ^ 16 = 43046721
dont le dernier chiffre est 1. La fonction doit être efficace possible parce que bien évidemment essayer de calculer 767456 ^ 981242
n’est pas très rapide.
J'ai essayé quelques méthodes mais je pense que le meilleur moyen de résoudre ce problème consiste à utiliser des séquences. Par exemple, tout nombre se terminant par 1
, lorsqu'il est élevé à une puissance, se terminera toujours par 1
. Pour 2
, le nombre résultant se terminera par l'un des 2, 4, 6 or 8
. Si un nombre est élevé à une puissance, le dernier chiffre du nombre résultant suivra un modèle basé sur le dernier chiffre de l'exposant:
1: la séquence est 1
2: la séquence est 2, 4, 8, 6
3: la séquence est 3, 9, 7, 1
4: La séquence est 4, 6
5: la séquence est 5
6: la séquence est 6
7: La séquence est 7, 9, 3, 1
8: La séquence est 8, 4, 2, 6
9: La séquence est 9, 1
0: la séquence est 0
Je pense que le moyen le plus simple de calculer le dernier chiffre global est de revenir en arrière dans la liste et de calculer le dernier chiffre de chaque calcul un par un jusqu'à ce que je revienne au début, mais je ne sais pas comment procéder.? Si quelqu'un pouvait aider ou suggérer une autre méthode aussi efficace ou plus efficace, cela serait apprécié.
J'ai ce code jusqu'à présent mais cela ne fonctionne pas pour les très grands nombres
def last_digit(lst):
if lst == []:
return 1
total = lst[len(lst)-2] ** lst[len(lst)-1]
for n in reversed(range(len(lst)-2)):
total = pow(lst[n], total)
return total%10
Edit: 0 ^ 0
devrait être supposé être 1
x ^ n = x ^ (n% 4) car le dernier chiffre a toujours une période de 4.
x ^2 ^3 ^4 ^5
1 1 1 1 1
2 4 8 6 2
3 9 7 1 3
4 6 4 6 4
5 5 5 5 5
6 6 6 6 6
7 9 3 1 7
8 4 2 6 8
9 1 9 1 9
Comme vous pouvez le constater, les 9 chiffres ont une période de 4, ce qui nous permet d’utiliser% 4 pour faciliter les calculs.
Il existe également une tendance si nous faisons cela% 4.
x ^0 ^1 ^2 ^3 ^4 ^5 ^6 ^7 ^8 ^9
1 1 1 1 1 1 1 1 1 1 1
2 1 2 0 0 0 0 0 0 0 0
3 1 3 1 3 1 3 1 3 1 3
4 1 0 0 0 0 0 0 0 0 0
5 1 1 1 1 1 1 1 1 1 1 (all %4)
6 1 2 0 0 0 0 0 0 0 0
7 1 3 1 3 1 3 1 3 1 3
8 1 0 0 0 0 0 0 0 0 0
9 1 1 1 1 1 1 1 1 1 1
Comme indiqué, il existe un motif pour chaque x lorsque n> 1. Par conséquent, vous pouvez voir que (x ^ n)% 4 = (x ^ (n + 4k))% 4 lorsque n> 1. Nous pouvons alors éviter les problèmes découlant de n = 0 et n = 1 en ajoutant 4 à n. En effet, si (x ^ n)% 4 = (x ^ (n + 4k))% 4, alors (x ^ n)% 4 = (x ^ (n% 4 + 4))% 4 également.
powers = [3, 9, 7, 1]
lastDigit = 1
for i in range(len(powers) - 1, -1, -1):
if lastDigit == 0:
lastDigit = 1
Elif lastDigit == 1:
lastDigit = powers[i]
else:
lastDigit = powers[i]**(lastDigit%4+4)
print(lastDigit%10)
C'est plus de maths que de programmation. Notez que toutes les séquences que vous avez répertoriées ont une longueur de 1, 2 ou 4. Plus précisément, x^4
se termine toujours par 0, 1, 5, 6
, tout comme x^(4k)
. Donc, si vous connaissez x^(m mod 4) mod 10
, vous connaissez x^m mod 10
.
Maintenant, pour calculer x2^(x3^(...^xn)) mod 4
. L'histoire est très similaire, x^2 mod 4
est ether 0
si x=2k
ou 1
si x=2k+1
(pourquoi?). Alors
si x2
est pair, il s'agit alors de 2
ou de 0
avec 2
uniquement lorsque x2 mod 4 == 2 and (x3==1 or (any x4,...xn == 0) )
.
si x2
est impair, alors x2^2 mod 4 == 1
, nous obtenons donc 1
si x3
est encore égal à x2 mod 4
.
Assez math, parlons de codage. Il y a peut-être des cas que je n'ai pas couverts, mais cela devrait fonctionner dans la plupart des cas.
def last_digit(lst):
if len(lst) == 0:
return 1
x = lst[0] % 10
if len(lst) == 1:
return x
# these number never change
if x in [0,1,5,6]:
return x
# now we care for x[1] ^ 4:
x1 = x[1] % 4
# only x[0] and x[1]
if len(lst) == 2 or x1==0:
return x[0] ** x1 % 10
# now that x[2] comes to the picture
if x1 % 2: # == 1
x1_pow_x2 = x1 if (x[2]%2) else 1
else:
x1_pow_x2 = 2 if (x1==2 and x[2]%2 == 1) else 0
# we almost done:
ret = x ** x1_pow_x2 % 10
# now, there's a catch here, if x[1]^(x[2]^...^x[n-1]) >= 4,
# we need to multiply ret with the last digit of x ** 4
if x[1] >=4 or (x[1] > 1 and x[2] > 1):
ret = (ret * x**4) % 10
return ret
En partant de votre idée de séquences et en la concrétisant, vous souhaiterez créer un dictionnaire capable de mapper toutes les séquences pertinentes.
mapping = {}
for i in range(1, 10):
mapping[i] = [i]
last_digit = i
while True:
last_digit *= i
last_digit = last_digit%10
if last_digit in mapping[i]:
break
else:
mapping[i].append(last_digit)
print(mapping)
Cela produit Sortie: mappage
{1: [1],
2: [2, 4, 8, 6],
3: [3, 9, 7, 1],
4: [4, 6],
5: [5],
6: [6],
7: [7, 9, 3, 1],
8: [8, 4, 2, 6],
9: [9, 1]}
Maintenant, la vraie logique peut commencer. La conclusion est que le motif se répète une fois la séquence terminée. Donc, peu importe la taille de la puissance, si vous utilisez simplement un modulo et déterminez quelle position de la séquence elle doit occuper.
def last_digit_func(lst, mapping):
if lst == []: #taken from OP
return 1
last_digit = lst[0] % 10
if 0 in lst[1:]: #Edge case 0 as a power
return 1
if last_digit == 0: #Edge case 0 at start
return last_digit
for current_power in lst[1:]:
if len(mapping[last_digit]) == 1:
return last_digit
ind = current_power % len(mapping[last_digit])
ind -= 1 #zero indexing, but powers start from 1.
last_digit = mapping[last_digit][ind]
return last_digit
test1 = [3, 4, 2]
print(last_digit_func(test1, mapping)) #prints 1
J'ai vérifié cela en calculant les puissances en python.
test2 = [767456 , 981242]
print(last_digit_func(test2, mapping)) #prints 6
Et j’ai essayé de vérifier cela en l’exécutant en python .... j’ai maintenant des regrets instantanés et mon programme essaie toujours de le résoudre. Tant pis :)