Проект Эйлера номер 338

Я застрял в Project Euler задаче 338. Вот что я сделал до сих пор...

Обозначим прямоугольник шириной и высотой x и y соответственно (x,y). Чтобы образовать новые прямоугольники, вы можете сократить своего рода лестницу по диагонали (как показано в описании задачи) с d ступенями. Но для формирования нового прямоугольника должны выполняться следующие условия: d|x и либо (d-1)|y, либо (d+1)|y. Затем новый прямоугольник становится либо (x/d*(d-1), y/(d-1)*d), либо (x/d*(d+1), y/(d+1)*d). Очевидно, что площадь нового прямоугольника такая же, как у старого прямоугольника.

Этого было достаточно, чтобы подтвердить, что G(10)=55 и G(1000)=971745, перебрав все соответствующие d и добавив все новые прямоугольники в набор, стараясь подсчитать (x,y) и (y,x) только один раз.

Основная проблема с этим методом заключается в том, что новый прямоугольник можно создать двумя разными способами. Например, (9,8) может превратиться как в (6,12), так и в (12,6) с d=3 и либо d-1, либо d+1, разделив y. Или другой пример преобразования (4,4) в (2,8) и (8,2) с d=2 и d=1 соответственно.

Затем мне посчастливилось прочитать эту запись в блоге. Это устраняет необходимость проверять наличие дубликатов, вместо этого выполняя поиск одной из сторон.

def F(w, h):
    if w&1 and h&1: return 0
    if w<h: w,h = h,w

    r = 0
    x = 1
    while x**2 <= w*h:
        if (w*h)%x!=0 or x==h:
            x += 1
            continue

        if w%(w-x)==0 or x%(x-h)==0:
            r += 1

        x += 1

    return r

def G(N):
    s = 0
    for w in range(1, N+1):
        for h in range(1, w+1):
            s += F(w,h)

    return s

G(1012) потребовало бы слишком много времени для решения, независимо от того, насколько быстра F. Я думаю, необходимо либо использовать какой-то алгоритм просеивания, в котором мы перебираем все x ‹ 1012, подсчитывая, сколько (w,h) удовлетворяют h ‹= w ‹= 1012, x|(w*h), x != h и (wx)|w или (xh)|x.

Я думаю, что алгоритм O(n2/3) должен быть возможен... но я застрял здесь!


Изменить: у меня нет доступа к форуму, так как я не могу его решить. Вот почему я прошу о помощи. Я ответил на большинство других вопросов и хочу ответить на этот вопрос сейчас!

Редактировать 2: я думаю, что рассмотрение областей по простым факторам — это тупик. Это потому, что существует 1024 различных областей. Прямоугольники с простыми площадями имеют 0 решений, прямоугольники с полупростыми площадями имеют 1 решение, если одно из простых чисел равно 2, в противном случае они имеют 0 решений. Но подсчет только всех полупростых решений занял бы слишком много времени, так как нам нужно было бы подсчитать все простые числа p, такие что 2*p ‹ 1024, что невозможно.

Редактировать 3: я убрал код:

def G(N):
    s = 0
    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and x%(w-x)==0 and x%(x-h)==0:
                    s -= 1

    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and w%(w-x)==0:
                    s += 1

    for x in range(1, N):
        for h in range(1, N+1):
            if x==h: continue
            for w in range(max(h, x**2//h), N+1):
                if (w*h)%x==0 and h%(x-h)==0:
                    s += 1

    return s

Я не думаю, что взлом кода грубой силы сработает. Помните, что достаточно просто подсчитать решения (x, w, h) каждой из этих трех подзадач. Последнее такое суммирование будет иметь ограничения 0 ‹ x ‹ N, 0 ‹ h ‹ N+1, x!=h, max(h, x2/h) ‹ w ‹ N+1, х|ш и хч|ч.

Я думаю, мы должны начать с предположения, что некоторое простое число p делится на x, w, h или даже x-h, а затем посмотреть, что мы можем сделать для других переменных. Если это сработает, можно рассмотреть pk для произвольного k.


person ForeverStuck    schedule 28.08.2011    source источник
comment
Если вы застряли, попробуйте другой вместо этого. Как говорится на сайте, Если вы не можете решить проблему, значит, вы не можете ее решить!.   -  person hammar    schedule 28.08.2011
comment
Вы также можете спросить на math.stackexchange.com   -  person agf    schedule 28.08.2011
comment
Кроме того, после того как вы отправите свое решение в Project Euler, вы получите доступ к форумам для решения проблемы; возможно, кто-то там уже нашел оптимальный алгоритм.   -  person Edwin    schedule 29.08.2011
comment
В этом случае ОП может вернуться и опубликовать свой лучший ответ после отправки.   -  person smci    schedule 29.08.2011
comment
Другой способ подумать об этом - с точки зрения простых множителей чисел, поэтому в примере 9 * 4 у вас есть 3 * 3 и 2 * 2, которые, конечно, можно расположить тремя другими уникальными способами, 3 и 3 * 2 * 2, 2 и 3*3*2, 3*2 и 3*2. Быстрее ли считать уникальные перестановки? Я понятия не имею, работает ли этот подход, но это еще один способ решить проблему. Удачи.   -  person Jackson    schedule 30.08.2011
comment
Вы распечатали G(0)...G(10) или около того и искали последовательность в oeis.org ?   -  person andrew cooke    schedule 03.09.2011
comment
Кроме того, упрощает ли дело (особенно ваше беспокойство о дубликатах) разделение примеров на этой странице на 2: два верхних — это горизонтальные слайды; нижняя - вертикальная горка. это просто вы d +/- 1, за исключением того, что вы можете рассматривать вертикаль как повернутую горизонталь. поэтому вы считаете только горизонтали, но включаете оба поворота для неквадратных форм. может быть, это не имеет значения, но это может упростить бухгалтерский учет.   -  person andrew cooke    schedule 03.09.2011
comment
Интересная проблема. Может быть, все дело в том, чтобы найти правильный метод записи. Я полагаю, что зацикливание в любом случае невозможно для экспоненциально растущего параметра. Я чувствую, что найти G на самом деле проще, чем F, поскольку вам не нужно находить факторы, а просто учитывать все. Обратите внимание, что все прямоугольники решения, похоже, состоят из N x (N+1) прямоугольников. Я подумаю об этом...   -  person Gerenuk    schedule 03.09.2011
comment
Я не понимаю, почему есть +10 голосов. Project Euler — это решение проблем САМИ.   -  person dfens    schedule 12.09.2011


Ответы (1)


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

def order(x,y):
    if x>=y:
        return (x,y)
    else:
        return (y,x)

N=1000
num=set()
for n in range(1, N+1):
    for a in range(1,N//n+1):
        for b in range(1,N//(n+1)+1):
            if a==b: continue
            num.add((order(a*n,b*(n+1)), order(b*n,a*(n+1))))

print(N, len(num))

Очевидно, что грубая сила или даже простой цикл над 10 ^ 12 невозможны, но, возможно, с помощью этого алгоритма в какой-то момент можно найти выражение в закрытой форме. Если бы не установленный символ num, это было бы выполнимо. Может быть, таким образом можно найти повторяющуюся точку.

Это может быть тупиковый путь, но все же довольно круто, что Python можно использовать для нотаций и работы с алгоритмами :)

Есть прогресс на вашей стороне?

person Gerenuk    schedule 04.09.2011