Runtime Error на удаленной среде при абсурдных обстоятельствах

На Timus.org решал задачи, код отсылал на компиляцию Python3.8 x64 и в 1 тривиальной задаче постоянно ловил Runtime Error на 10 тесте. Заключил основное тело программы в try: <...> except ZeroDivisionError: print(0)(чтобы заменить runtime error на wrong answer и заключая разные куски кода, найти проблемный) и стал ловить Runtime error на 8 тесте. Как заключение кода в try: <...> except ZeroDivisionError: print(0) , где <...> заведомо рабочий код(проходит тесты 8 и 9) может вызывать Runtime error, там где раньше он исправно работал

#Получаем простое число по его порядковому номеру где порядок числа 2 == 0
smpllst=[2,3,5,7,11]
def simpleNum(a):
    global smpllst
    if a>len(smpllst):
        for i in range(len(smpllst),a):
            nmbr=smpllst[len(smpllst)-1]+1
            smpl=False
            while not smpl:
                nmbr+=1
                smpl=True
                for u in smpllst:
                    if (nmbr%u)==0: 
                        smpl=False
                        break
            smpllst+=[nmbr]
    return smpllst[a]
#Убираем еденички из списка 
def rmv1(lst):
    i=0
    while i<len(lst):
        if lst[i]==1:
            lst.pop(i)
        else:
            i+=1

#считываем длину последовательности перестановок(1строка),считываем в rdr саму последовательность 
longitude=int(input())
rdr2=tuple(map(int,input().split()))
rdr=[]
for i in range(longitude): rdr+=[rdr2[i]]
#в combine записываем длину всех изолированных перестановок 
cmbn=[]
for i in range(len(rdr)):
    if rdr[i]!=0:
        lp=1
        pntr=rdr[i]
        while i!=pntr-1:
            lp+=1
            tmp=rdr[pntr-1]
            rdr[pntr-1]=0
            pntr=tmp
        cmbn+=[lp]
#Ищем наименьший общий делитель для всех малый перестановок;пишем его в rslt
rmv1(cmbn)
rslt=1
q=0
while len(cmbn)>0:
    dvsr=simpleNum(q)
    have1=False
#Техномагия: c try except runtime error на 8 тесте,без них на 10
#Пытаюсь превратить runtime error в wrong answer    
    try:    
        for i in cmbn:
            if (i % dvsr)==0:
                have1=True
                break
        if have1:
            rslt=rslt*dvsr
            for i in range(len(cmbn)):
                if (cmbn[i]%dvsr)==0 : cmbn[i]=cmbn[i]//dvsr
            rmv1(cmbn)
    except ZeroDivisionError:
        print(-1)
    else:
        q+=1
#выводим степень перестановки(сколько раз её нужно применять на саму себя, чтобы получить исходную последовательность)
print(rslt)

Timus.org задача 1024(школьная)


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Я проверил вашу программу на таком входе:

41
2 1 5 3 4 10 6 7 8 9 17 11 12 13 14 15 16 28 18 19 20 21 22 23 24 25 26 27 41 29 30 31 32 33 34 35 36 37 38 39 40

Результат:

Traceback (most recent call last):
  File "original.py", line 49, in <module>
    dvsr=simpleNum(q)
  File "original.py", line 17, in simpleNum
    return smpllst[a]
IndexError: list index out of range

Ситуацию можно улучшить такой правкой:

< if a>len(smpllst):
<     for i in range(len(smpllst),a):
--------
> if a>=len(smpllst):
>     for i in range(len(smpllst),a+1):

P.S. Вычисление НОК не требует разложения числа на простые множители. Через НОД проще:

def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


def lcm(seq):
    lcm = 1
    for v in seq:
        lcm = lcm * v // gcd(lcm, v)
    return lcm

В Питоне 3.9 есть встроенная функция math.lcm, но у вас предыдущий Питон.

Длины циклов будет проще считать если перестановку из диапазона [1, N] перевести в [0, N-1].

Всё вместе:

def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


def lcm(seq):
    lcm = 1
    for v in seq:
        lcm = lcm * v // gcd(lcm, v)
    return lcm


def loops(p):
    f = [False] * len(p)
    for i in range(len(p)):
        if not f[i]:
            c = 0
            while not f[i]:
                c += 1
                f[i] = True
                i = p[i]
            yield c


input()
p = [int(w) - 1 for w in input().split()]
print(lcm(loops(p)))
→ Ссылка