Количество различных решений xy+yz+ xz = N

Я пытался решить проблему на spoj. Вот ссылка на проблему.

http://www.spoj.pl/problems/TAP2012B/

Из того, что я интерпретировал, мне нужно найти количество решений уравнения xy+yz+xz = N, где n задано нам. x>=y>=z z может быть равно нулю. Но x и y не могут. Я попытался решить эту проблему, реализовав 3 цикла for (плохой подход). Он дает правильный ответ, но слишком медленно. Кроме того, другие люди решили эту проблему практически мгновенно (0,00). Поэтому я уверен, что существует совершенно другой подход к этой проблеме. При N = 20 число различных решений равно 5: (6,2,1) (5,4,0) (10,2,0) (4,2,2,) (20,1,0)


person blkmgcbhl    schedule 08.10.2012    source источник
comment
На моей машине он работает 5 секунд для N = 10000. Это реализация Python. Это медленно или хорошо?   -  person ondrejdee    schedule 04.07.2013
comment
Мой пример работает 0,12 с. для 9747, и я все еще думаю, что у него есть потенциал оптимизации.   -  person akalenuk    schedule 04.07.2013
comment
Очень хорошо! +1 к вашему решению.   -  person ondrejdee    schedule 04.07.2013


Ответы (3)


Может быть, есть какое-то блестящее решение, основанное на теории чисел. Но простое переосмысление задачи также может уменьшить сложность алгоритма.

Например, нам не нужен третий цикл, так как мы можем вычислить z как (N - x*y)/(x+y). И нам не нужно прогонять y до x каждый раз, поскольку мы знаем, что z не является отрицательным, поэтому N >= xy.

N = 9747
for x in range(1, N+1):
    max_y = min( N / x, x) 
    for y in range(1, max_y+1):
        if (N - x*y) % (x+y) == 0:
            z = (N - x*y) / (x+y)
            if z <= y:
                print x,y,z
person akalenuk    schedule 04.07.2013

Вы приближаетесь к правильному направлению, будет 3 вложенных цикла, но постарайтесь уменьшить нет. цикл сработает.... Внимательно следите за вопросом и условиями.....

person Paras    schedule 04.07.2013

Вы явно учитесь, так что было бы лучше, если бы вы все делали сами, но теперь у вас есть отличное решение от akalenuk, и я надеюсь, что вы тоже чему-то научитесь из него.

Если вы одновременно изучаете python, я дам вам решение, эквивалентное решению akalenuk, но на этот раз с пониманием списка, что является очень полезным механизмом:

N = 10000

print [(x, y, z)
       for x in range(1, N+1)
       for y in range(1, min( N/x, x) + 1 )
       for z in [ (N - x*y) / (x+y) ] 
       if (N - x*y) % (x+y) == 0
       if z <= y]

Дело в сокращении пространства решения. Приведенный выше код уже достаточно оптимизирован. Вы можете начать с чего-то вроде:

N = 10000

print [(x, y, z)
       for x in range(1, N+1)
       for y in range(1, x+1 )
       for z in range(y+1) 
       if N == x*y + y*z + x*z]

Это будет длиться довольно долго. Итак, первым пунктом оптимизации может быть добавление условия на y:

N = 10000

print [(x, y, z)
       for x in range(1, N+1)
       for y in range(1, x+1 )
       if x*y <= N
       for z in range(y+1) 
       if N == x*y + y*z + x*z]

Это уже значительно сокращает время, так как для неперспективных y цикл z вообще не запускается. Затем вы заметите, что вы можете заменить этот оператор if явным вычислением максимума y, как это сделал akalenuk:

N = 10000

print [(x, y, z)
       for x in range(1, N+1)
       for y in range(1, min(x, N/x) +1)
       for z in range(y+1) 
       if N == x*y + y*z + x*z]

Это снова ускорит его.

Пока вы учитесь, я рекомендую вам попробовать все это, а также свои собственные, засечь время и извлечь из этого уроки. Я также рекомендую попробовать разные похожие решения.

person ondrejdee    schedule 04.07.2013