Je continue d’avancer sur ce problème ci mais j’aimerais essayer autre chose. Le problème c’est que je me perds un peu dans l’immense liste de problèmes. J’ai regardé un peu les problèmes de programmation dynamique mais j’ai aucune idée duquel prendre pour commencer. Du coup je suis ouvert à vos suggestions (je ne me restreint pas à SPOJ, faites vous plaisir).
Je fais en même temps mes implémentations de divers algorithmes et structures de données classiques (les tris, arbres, tas…). Si vous êtes ok j’aimerais bien vous envoyer le code et que vous me disiez comment mieux faire (en complexité mais surtout en "pythonicité").
Encore merci de votre aide, le billet arrive dès que j’ai optimisé ce fichu problème !
Edit : @Yoch Le problème de ton astuce c’est qu’il faut faire un cas particulier pour 2. Je n’y avais pas réflechi avant de l’implémenter
Edit 2:
J’ai eu une "bonne" idée, je me suis dit que je pouvais utiliser un générateur pour itérer pendant mon crible. Voici ce avec quoi je suis arrivé :
| prime = (n for n, is_prime in enumerate(nb[3:], start=3) if is_prime)
for p in prime:
print(p)
nb[p**2::2*p] = [False] * int(math.ceil((len(nb)-p*p) / (2*p)))
output.append(p)
|
Mais j’ai constaté une chose sur le fonctionnement du générateur : il évalue toute les sorties sans prendre en compte l’évolution du tableau sur lequel il itère. On a pas moyen d’éviter ça ? C’est plus par curiosité sur quelque chose que je n’ai jamais utilisé autre qu’en tuto.
Edit 3 : Après un peu de travail j’ai implémenté un crible pour l’intervalle qui nous intéresse. Sauf que je me prend encore un TLE, je désespère un peu de comprendre pourquoi très honnêtement.
Voici mon code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 | # Prime1 on SPOJ - SpheOnlineJudge.com
import sys
import math
import bisect
def prime_sieve(end):
nb = [False, False] + [True] * (end - 1) # 0 and 1 to False
nb[2**2::2] = [False] * int(math.ceil((len(nb) - 4) / 2))
for i in range(3, math.ceil(math.sqrt(len(nb)))):
if nb[i]:
nb[i**2::2*i] = [False] * math.ceil((len(nb)-i*i) / (2*i))
return [n for n, is_prime in enumerate(nb) if is_prime]
def main():
nb_test = int(sys.stdin.readline())
cases = []
max_end = 0
for e in range(nb_test):
start, end = map(int, sys.stdin.readline().split(" "))
cases.append({"start": start, "end": end})
if max_end < end:
max_end = end
primes = prime_sieve(math.ceil(math.sqrt(max_end)))
for case in cases:
start, end = case["start"], case["end"]
if start == 1:
if end >= 2:
start = 2
else:
print()
continue
nb = [True] * (end - start + 1)
max_p = bisect.bisect(primes, math.sqrt(end))
min_p = bisect.bisect_left(primes, start)
[print(i) for i in primes[min_p:max_p]] # cette ligne permet d'afficher les nombres premiers entre start et sqrt(end)
for p in primes[:max_p]:
try:
first = next(filter(lambda i: (start + i) % p == 0,
range(len(nb))
)
)
nb[first::p] = [False] * len(nb[first::p]) # Parce qu'ici ils seront mis à False
except StopIteration:
break
[print(i) for i, is_prime in enumerate(nb, start=start) if is_prime]
print() # New line and each test case
if __name__ == '__main__':
main()
|
Merci encore du temps que vous passez pour moi