LINUX.ORG.RU

Диофант - Арифметика

 


0

2

Диофант в 3-веке написал Арифметику, состоящую из 13 книг, из которых до нас дошли всего 6
Эта книга послужила толчком для развития теории чисел спустя почти полторы тысячи лет
В этой книге он ставит и решает алгебраические уравнения с несколькими неизвестными

В частности, в третьей книге есть задача под номером 5:
Найти три числа, сумма которых равна квадрату и такие, чтобы два из них, взятые вместе, превышали оставшееся третье на квадрат.

Т.е.. есть система из двух уравнений:
a+b+c=d^2
a+b-c=e^2

Диофант например находит дробные решения: 8.5, 32.5, 40

Задача: написать программу, которая находит бесконечно много таких троек чисел, причем в целых числах


★★★★★

Второе условно поясни: из трех чисел a, b, c должны выполняться все три условия
a+b-c=квадрат
a+c-b=квадрат
b+c-a=квадрат

Или только одно из них?

anonymous
()
import itertools
for i in map(lambda x: x**2, itertools.count()):
    print("{}, 0, 0".format(i))
deadNightTiger ★★★★★
()

переобозначаешь
a+b=x
d^2=D
e^2=E,

x+c=D
x-c=E,

x=(D+E)/2
c=(D-E)/2

перебираешь любые квадраты целых чисел D > E с условием, что они оба четные или нечетные, чтобы делилось на 2. Например,

D=121,
E=81

=> x = 101, c = 20
=> a+b - любые дающие в сумме 101, например a=4, b=97

Bell
()

Задача: написать программу, которая находит бесконечно много таких троек чисел, причем в целых числах

Не мучайся, реши перебором.

no-such-file ★★★★★
()

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

nezamudich ★★
()
Ответ на: комментарий от anonymous

Лишь с одним из этих условий задача ещё более тривиальна. Должны быть выполнены все, конечно же.

nezamudich ★★
()
Ответ на: комментарий от nezamudich

О да, путь настоящего лиспера

«When in doubt, use brute force» (с) Кен Томпсон. Учись сынок.

no-such-file ★★★★★
()

Про систему несовсем верно. Мы имеем след. систему уравнений:

{ a+b+c = k^2
{ a+b-c = q1^2
{ a+c-b = q2^2
{ b+c-a = q3^2
Сложив три последний уравнения получаем:
a+b+c = q1^2+q2^2+q3^2 = k^2
Т.е. Пифагорова четверка. К этому еще вернемся, а пока выведем, a, b, c:
{ 2c = k^2-q1^2
{ 2b = k^2-q2^2
{ 2a = k^2-q3^2
Т.е. q1, q2, q3, k должны быть одной четности. Очевидно, что четный вариант мы можем получить домножением q1, q2... на 2, тогда будем будем искать `примитивные` четверки, т.е. НОД(q1, q2, q3) = 1. В Википедии есть две параметризации.

Из первой следует, что нет таких четверок, в которых все числа нечетные. Тогда будем искать примитивные четверки, и домножать их на 2.

Вторая параметризация хорошо подходит для перебора. Для начала немного отвелчемся от задачи и будем думать, как составить алгоритм нахождения натуральных корней уравнения "a^2 + b^2 + c^2 = d^2" или их удвоенного значения. Пусть a и b будут разной четности, что облегчает наш перебор. Тогда пусть s = a^2+b^2, а p — такой делитель s, что p^2<s Тогда:

2c = s/p - p
2d = 2c + 2p
Осталось только a и b домножить на 2, и мы можем найти решения нашего уравнения.

Вот прототип алгоритм на Python:

from math import sqrt

def alg(maxq1):
    for q1 in range(2, maxq1+1, 2):
        for q2 in range(1, q1, 2):
            s = q1*q1 + q2*q2
            for p in range(1, int(sqrt(s))):
                if s % p == 0:
                    q1 <<= 1; q1 = q1*q1
                    q2 <<= 1; q2 = q2*q2
                    q3 = (s//p) - p;
                    k = (q3 + (p<<1));
                    q3 = q3*q3; k = k*k
                    yield ((k-q1)>>1, (k-q2)>>1, (k-q3)>>1)

Прототип потому, что уже пятым числом выдает нечто отрицательное (может быть так и надо :D), ну и при вызове alg(6) или больше OverflowError. Пока сыро, но уже пол второго и я не в состоянии сейчас что-либо исправлять. Не знаю, как оценить сложность алгоритма, но это явно лучше чем тупой перебор за O(n^3) и это без учета поиска квадратов/корней.

destabilizer
()
let go = [(a,b,c) | a <- [1..] , b <- [1..a] , c <- [1..b], isSquare (a+b+c), isSquare (a+b-c) || (isSquare (a+c-b))] where isSquare x = let t = sqrt $ fromIntegral x in t == fromIntegral (round t)
> take 100 go
[(4,4,1),(6,6,4),(7,6,3),(8,6,2),(9,6,1),(9,8,8),(10,8,7),(11,8,6),(12,8,5),(12,12,1),(13,8,4),(13,13,10),(14,8,3),(14,12,10),(15,8,2),(15,11,10),(16,8,1),(16,10,10),(16,16,4),(17,10,9),(17,16,3),(18,10,8),(18,16,2),(19,10,7),(19,16,1),(19,18,12),(20,10,6),(20,17,12),(20,20,9),(21,10,5),(21,16,12),(21,20,8),(22,10,4),(22,15,12),(22,20,7),(23,10,3),(23,14,12),(23,20,6),(24,10,2),(24,13,12),(24,20,5),(24,24,1),(24,24,16),(25,10,1),(25,12,12),(25,20,4),(25,24,15),(25,25,14),(26,12,11),(26,20,3),(26,24,14),(27,12,10),(27,20,2),(27,23,14),(27,24,13),(28,12,9),(28,20,1),(28,22,14),(28,24,12),(28,28,25),(29,12,8),(29,21,14),(29,24,11),(29,28,24),(30,12,7),(30,20,14),(30,24,10),(30,28,23),(30,30,4),(31,12,6),(31,19,14),(31,24,9),(31,28,22),(31,30,3),(32,12,5),(32,18,14),(32,24,8),(32,28,21),(32,30,2),(33,12,4),(33,17,14),(33,24,7),(33,28,20),(33,30,1),(33,32,16),(34,12,3),(34,16,14),(34,24,6),(34,28,19),(34,31,16),(34,34,32),(35,12,2),(35,15,14),(35,24,5),(35,28,18),(35,30,16),(35,33,32),(36,12,1),(36,14,14),(36,24,4)]
qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
N = 10

for d in xrange(2, N):
    D = (d+1)**2
    for e in xrange(d%2, d, 2):
        E = (e+1)**2
        x = (D+E)/2 
        c = (D-E)/2
        for a in xrange(1, x):
            b = x - a
            print(a, b, c, a+b+c, a+b-c)
(1, 4, 4, 9, 1)
(2, 3, 4, 9, 1)
(3, 2, 4, 9, 1)
(4, 1, 4, 9, 1)
(1, 9, 6, 16, 4)
(2, 8, 6, 16, 4)
(3, 7, 6, 16, 4)
(4, 6, 6, 16, 4)
(5, 5, 6, 16, 4)
(6, 4, 6, 16, 4)
(7, 3, 6, 16, 4)
(8, 2, 6, 16, 4)
(9, 1, 6, 16, 4)
(1, 12, 12, 25, 1)
(2, 11, 12, 25, 1)
...
Bell
()

Все, я написал нормально свой алгоритм. Вот два алгоритма:

def alg(maxq1):
    for q1 in range(2, maxq1+1, 2):
        q1 = q1*q1
        for q2 in range(1, q1+1, 2):
            q2 = q2*q2
            s = q1 + q2
            for p in range(1, int(sqrt(s)-0.0001)+1, 2):
                if s % p == 0:
                    q3 = ((s//p)-p)>>1
                    q3 = q3*q3
                    yield ((q1+q2)<<1, (q1+q3)<<1, (q2+q3)<<1)


def brute_alg(maxq1):
    L = []
    for q1 in range(2, maxq1+1, 2):
        q1 = q1*q1
        for q2 in range(2, q1+1, 2):
            q2 = q2*q2
            for q3 in range(2, q2+1, 2):
                q3 = q3*q3
                k = q1 + q2 + q3
                t = sqrt(k)
                if round(abs(t - int(t)), 6) == 0.0:
                    yield (k-q1)>>1, (k-q2)>>1, (k-q3)>>1
Один тот что я описывал выше (правда здесь кое-какие изменения), и brute алгоритм который ищет четные пифагоровы четверки и от них находит решения этого уравнения.

Кто говорил про Brute Force — для таких целей не катит никак. Вот что у меня получилось по времени:

alg(10) 0.1 | brute_alg(10) 0.54

alg(20) 0.12 | brute_alg(20) 40.67 (!!!)

Т.е. уже на 20 это ооочень долго, на 30 и дальше я уже не дождался. Но при этом alg(50) 1.2, т.е. разница колоссальна.

Буду рад если кто-нибудь оценит сложность алгоритма, т.к. тут не очень ясно как это сделать. ПС: Есть ли эффективные алгоритмы нахождения целой части квадрата числа?

destabilizer
()
Ответ на: комментарий от destabilizer

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

Bell
()
Ответ на: комментарий от Bell

Во-первых, как вы уже заметили, этот вывод можно сделать из примера. В противном случае, странное было бы совпадение, вам не кажется?

Во-вторых, в аналогичных задачах по математике (целые и натуральные числа, комбинаторика) часто опускается слово любые, зато если подразумевается какой-то конкретный набор то всегда (из личного опыта) указывается «некоторые», «вполне определенные» и т.п.

В-третьих, если вы ознакомитесь с трудами самого Диофанта, то поймете, что имел он в виду именно ту систему, которую я описал выше.

destabilizer
()
Ответ на: комментарий от destabilizer

В условии точно сказано и словами, и системой уравнений, что второму условию удовлетворяет одно число. А Диофант может предложить свои оригинальные формулировки и даже открыть новую тему :) Тем более что автор этой после создания не проявил к ней никакого интереса.

Bell
()
Ответ на: комментарий от Bell

Словами точь в точь скопировано с русского перевода Арифметики. А про систему из 2ух уравнений — это домыслы ТС, в первоисточнике который и указывает сам ТС речь идет о *нувыпонели*.

destabilizer
()

Я специально привел не самую трудную задачу из Арифметики Диофанта.. У него есть задачи поинтереснее. Например - разложить квадрат на два квадрата. Все знают, что 25 можно разложить на 9 и 16. Но не все знают, что 25 можно разложить на два рациональных квадрата бесчисленным числом способов, например :

(40/17)^2 + (75/17)^2 = 25

(72/17)^2 + (135/17)^2 = 25 и т.д.

Кстати, сам Диофант приводит дробное решение: 16 = 256/25 + 144/25 Диофант не описывает алгоритм решения своих задач, создается впечатление, что они решены по наитию, но это конечно не так. Разложить квадрат на два квадрата можно например так:

for a in range(5,10):
     k=4
     x = Decimal(2*a*k)/Decimal((k**2) + 1) 
     y = Decimal(a * (((k**2)-1))/Decimal(((k**2)+1)))
     if Decimal(x**2) + Decimal(y**2) == a**2 and y > 0:
       print '%s x=%s/%s y=%s/%s x^2=%.2f y^2=%.2f' % (a**2, 2*a*k, k**2+1, a * (k**2-1), (k**2+1), x**2, y**2 )

kto_tama ★★★★★
() автор топика
Ответ на: комментарий от kto_tama

Но не все знают, что 25 можно разложить на два рациональных квадрата бесчисленным числом способов

Не самое удивительное дело — взять a^2 + b^2 = c^2, разделить на c^2 и умножить на 25. Одно действие.

nezamudich ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.