2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Разложение числа в сумму двух квадратов
Сообщение26.05.2023, 17:43 


20/02/20
67
В сообщении https://dxdy.ru/topic14229-345.html wrest писал:
Для разложения числа в сумму двух квадратов натурпльных чисел, насколько мне известно, простых путей нет.
Я тут навскидку составил программку на PARI(наверняка не оптимальную,но Dmitriy40 сразу увидит)
Код:
sq(n)={my(v=apply(x->x^2,vector(sqrtint(n-1),i,i)));u=[];f=0;
for(i=1,n-1,v=concat(v,v[i]));
forsubset([#v,2],x,u=concat(u,[vecsort(vecextract(v,x))]));u=Set(u);
for(i=1,#u,if(vecsum(u[i])==n,f++;print(n,"=",sqrtint(u[i][1]),"^",2,"+",sqrtint(u[i][2]),"^",2)));
if(f==0,print("Not squares")}

Например
Код:
sq(25)
25=3^2+4^2
sq(32)
32=4^2+4^2
sq(82)
82=1^2+9^2
sq(185)
185=4^2+13^2
185=8^2+11^2
sq(91)
Not squares

Главная головная боль-в создании массива из сочетаний.А как иначе?

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение26.05.2023, 19:25 
Заслуженный участник


20/08/14
11182
Россия, Москва
genk в сообщении #1595450 писал(а):
А как иначе?
Ну ... Я бы сделал так:
Код:
? sq(n)=my(x,y); for(x=1,sqrt(n/2), if(issquare(n-x^2,&y), print(n,"=",x,"^2+",y,"^2")));
? sq(91)
? sq(185)
185=4^2+13^2
185=8^2+11^2
? sq(1234567890123456)
time = 6,491 ms.
? sq(98765432^2+12345678^2)
9907026323426308=12345678^2+98765432^2
9907026323426308=23606018^2+96694272^2
9907026323426308=30889448^2+94619598^2
9907026323426308=41551008^2+90446338^2
time = 18,706 ms.
Время $O(\sqrt{n})$, памяти не требуется вообще.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 10:22 


20/02/20
67
Dmitriy40
Класс! Ex ungue leonem pingere.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 13:14 


05/09/16
11547
Dmitriy40 в сообщении #1595458 писал(а):
Ну ... Я бы сделал так:
Код:
? sq(n)=my(x,y); for(x=1,sqrt(n/2), if(issquare(n-x^2,&y), print(n,"=",x,"^2+",y,"^2")));

Я бы добавил проверку на наличие решений
Код:
sq(n)=my(x,y); if(setsearch(Set(factor(n)[, 1]%4), 1), print("Solutions:");for(x=1,sqrt(n/2), if(issquare(n-x^2,&y), print(n,"=",x,"^2+",y,"^2"))),print("No solutions"));

Тогда перебор будет только если решения есть. А если решений нет, будет быстрее.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 14:26 


05/09/16
11547
Ой, что-то я накосячил. Предыдущее сообщение недействительно.

-- 27.05.2023, 15:24 --

Попытка номер 2.
Функция sqn() вычисляет количество представлений входного числа суммой двух натуральных квадратов

Код:
sqn(c)=my(v=factor(c),a0=if(v[1,1]==2,v[1,2],0),v1=v,b=1;b4=0);for(i=1,#v[,1],b4=v[i,1]%4;if(b4==1,b=b*(v[i,2]+1));if(b4==3,if(v[i,2]%2!=0,return(0))));if(b%2==0,return(b/2));return((b-(-1)^a0)/2)


Функция sqw() обращается к функции sqn(), затем перебирает и печатает решения пока не найдёт их все.

Код:
sqw(n)=my(x,y,c=sqn(n),c0=0);if(c==0,print("No solutions");return());print(c," solutions:");for(x=1,sqrt(n/2), if(issquare(n-x^2,&y), print(n,"=",x,"^2+",y,"^2");c0++;if(c0==c,return())));


Надеюсь, косяков нет :mrgreen:
Ускорение за счет:
1. Ускоряется если решений нет.
2. Перебор заканчивается когда найдены все решения.

P.S. Я не силён в while и until, так что заколхозил просто выход из for
P.P.S. Идея как считать количество решений взята отсюда: https://mathworld.wolfram.com/SumofSquaresFunction.html

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 15:54 


05/09/16
11547
Вольфрам разлагает число 489886592769624989886788 в сумму двух квадратов влёт.
https://www.wolframalpha.com/input?i=Po ... 2C2%2C2%29
Получается 2 решения (хотя именно это число в доках по функции, так может просто из базы достают).
489886592769624989886788=179075995118^2+676622775808^2
489886592769624989886788=180837148448^2+676154212078^2


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

Функция sqn() из поста выше, конечно, вычисляет количество решений мгновенно. Так что вопрос именно в поиске их.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 16:07 


18/09/21
1685
Как представить произвольное число суммой квадратов
Теорема Ферма — Эйлера
Представление чисел суммой двух квадратов и эллиптические кривые

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 16:43 


05/09/16
11547
zykov
Ссылки не дают ответа на вопрос как разложить число на сумму двух квадратов натуральных чисел...
Например, берём "пробное" число
$489886592769624989886788=2^2\cdot 6361^1 \cdot 19253521174721937977^1$
Остатки от деления на 4 простых множителей
$2;1;1$
И что дальше? Знаем, что искомых представлений два штуки.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 17:34 


18/09/21
1685
Если вместо перебора "x=1,sqrt(n/2)" делать перебор "x=sqrt(n/2),sqrt(n)", то будет несколько короче (где-то в $2.4$ раза).

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 17:41 


05/09/16
11547
zykov в сообщении #1595548 писал(а):
Если вместо перебора "x=1,sqrt(n/2)" делать перебор "x=sqrt(n/2),sqrt(n)", то будет несколько короче (где-то в $2.4$ раза).

Хорошее замечание, действительно.
Переопубликую с учетом этого (а то у меня там помарка нашлась)
Код:
sqn(c)=my(v=factor(c),a0=if(v[1,1]==2,v[1,2],0),v1=v,b=1,b4=0);for(i=1+(a0>1),#v[,1],b4=v[i,1]%4;if(b4==1,b=b*(v[i,2]+1));if(b4==3,if(v[i,2]%2!=0,return(0))));if(b%2==0,return(b/2));return((b-(-1)^a0)/2)

sqw(n)=my(x,y,c=sqn(n),c0=0);if(c==0,print("No solutions");return());print(c," solutions:");for(x=floor(sqrt(n/2))+1, sqrt(n),if(issquare(n-x^2,&y), print(n,"=",x,"^2+",y,"^2");c0++;if(c0==c,return())));

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 18:00 


18/09/21
1685
Если $x^2 + y^2 = n$, то $(x+y)^2 + (x-y)^2 = 2n$.
Значит степени двойки можно сразу выкинуть и раскладывать нечётное.

-- 27.05.2023, 18:09 --

Ещё теорема Фиббоначи: Если целые числа N и M могут быть представлены в виде суммы двух квадратов, то их произведение так же может быть представлено в виде суммы двух квадратов.
$$(a^2+b^2) (c^2+d^2) = (ac+bd)^2 + (ad-bc)^2$$
Если удаётся разложить число на множители, то можно каждый множитель разложить на сумму.
Тут правда возможно некоторые пары будут потеряны.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 18:29 


05/09/16
11547
zykov в сообщении #1595553 писал(а):
Если удаётся разложить число на множители, то можно каждый множитель разложить на сумму.

Ну вот в "пробном числе" есть очень большой простой множитель:
wrest в сообщении #1595544 писал(а):
Например, берём "пробное" число
$489886592769624989886788=2^2\cdot 6361^1 \cdot 19253521174721937977^1$

При этом $2^2\cdot 6361^1=138^2+80^2$
Вольфрам раскладывает
19253521174721937977=3098660171^2+3106738856^2
Но как это сделать нам? Хотя тут нам конечно повезло, ибо оба числа практически равны корню из половины раскладываемого и перебор быстро отрабатывает.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 18:36 


18/09/21
1685
Да, $6361$ легко раскладывается. Единственный вариант $6361=40^2+69^2$.

wrest в сообщении #1595558 писал(а):
у вот в "пробном числе" есть очень большой простой множитель
Его и надо раскладывать.
Всё же меньше, чем исходное число.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 18:44 


05/09/16
11547
zykov в сообщении #1595560 писал(а):
Единственный вариант

Ессно, простые если и раскладываются, то единственным образом.

 Профиль  
                  
 
 Re: Разложение числа в сумму двух квадратов
Сообщение27.05.2023, 18:55 


18/09/21
1685
wrest в сообщении #1595558 писал(а):
Вольфрам раскладывает
19253521174721937977=3098660171^2+3106738856^2
Да, вольфрам прямо сразу выдаёт. Значит не делает полный перебор.
Видимо есть какой-то более быстрый алгоритм (может что-то более общее про Диофантовы уравнения).
Встречал какое-то упоминание про разложение корня числа в цепную дробь, что как-то помогает.
Но пока не нашел деталей, как именно.

-- 27.05.2023, 19:18 --

Вот здесь приводят какой-то алгоритм: https://math.stackexchange.com/question ... to-a-prime

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 44 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group