Напишите программу, которая проверяет гипотезу Эрдеша – Страуса


15

Напишите программу, которая проверяет гипотезу Эрдеша – Страуса .
Программа должна принять в качестве входных данных одно целого числа n( 3 <= n <= 1 000 000) и печать тройки целых чисел , удовлетворяющих идентичность 4/n = 1/x + 1/y + 1/z, 0 < x < y < z.

Самый короткий код выигрывает.

Несколько примеров:

3 => {1, 4, 12}
4 => {2, 3, 6}
5 => {2, 4, 20}
1009 => {253, 85096, 1974822872}
999983 => {249996, 249991750069, 62495875102311369754692}
1000000 => {500000, 750000, 1500000}

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


Программа должна выводить каждое возможное решение или только одно? Например, есть 2 возможности для n = 5.
Излин

1
Только одного достаточно.
Сомниум

2
Это несколько вводит в заблуждение, что ваш единственный контрольный пример не является допустимым вводом в соответствии со спецификацией.
Питер Тейлор

Я изменю это, пример добавил durron597.
Сомниум

Я добавил этот пример, потому что мое исследование показало, что это было особенно трудно сделать. Самые сложные - простые числа, которые соответствуют {1, 121, 169, 289, 361, 529}модулю 840.
durron597

Ответы:


12

Рубин, 119 106 символов

f=->s,c,a{m=s.to_i;c<2?m<s||(p a+[m];exit):(1+m...c*s).map{|k|f[s/(1-s/k),c-1,a+[k]]}}
f[gets.to_r/4,3,[]]

Код использует минимальные границы для каждой переменной, например n/4<x<3n/4, аналогично для y. Даже последний пример возвращается мгновенно (попробуйте здесь ).

Примеры:

> 12
[4, 13, 156]

> 123
[31, 3814, 14542782]

> 1234
[309, 190654, 36348757062]

> 40881241801
[10220310451, 139272994276206121600, 22828913614743204775214996005450198400]

Отличное решение, однако границы немного тесные, потому что ваша программа за 1 000 000 находит лучшее решение (см. Мой пример).
Сомниум

1
@ user2992539 Мой код возвращает первое лексикографическое решение (250001 <500000).
Говард

7

Mathematica 62

Это простое ванильное решение прекрасно работает - большую часть времени.

f@n_ := FindInstance[4/n == 1/x + 1/y + 1/z && 0 < x < y < z, {x, y, z}, Integers]

Примеры и сроки (в секундах)

AbsoluteTiming[f[63]]
AbsoluteTiming[f[123]]
AbsoluteTiming[f[1003]]
AbsoluteTiming[f[3003]]
AbsoluteTiming[f[999999]]
AbsoluteTiming[f[1000000]]

{0.313671, {{x -> 16, y -> 1009, z -> 1017072}}}
{0.213965, {{x -> 31, y -> 3814, z -> 14542782}}}
{0.212016, {{x -> 251, y -> 251754, z -> 63379824762}}}
{0.431834, {{x -> 751, y -> 2255254, z -> 5086168349262}}}
{1.500332, {{x -> 250000, y - > 249999750052, z -> 1201920673328124750000}}}
{1.126821, {{x -> 375000, y -> 1125000, z -> 2250000}}}


Но это не является полным решением. Есть некоторые цифры, которые он не может решить. Например,

AbsoluteTiming[f[30037]]
AbsoluteTiming[f[130037]]

{2.066699, FindInstance [4/30037 == 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z}, целые числа]}
{1.981802, FindInstance [4/130037 = = 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z}, целые числа]}


Правильный инструмент для правильной работы. +1
Уильям Барбоза

3
@WilliamBarbosa Я бы сказал, что FindInstanceэто не тот инструмент, который не может гарантировать результат ...
Говард

2
@Howard Я говорил о Mathematica, на самом деле
Уильям Барбоза

Reduceкажется, решает упрямые случаи, хотя это часто занимает время. Например, 15 минут, чтобы найти 82 решения для n = 10037.
DavidC

3

C #

Disclamer: это не серьезный ответ

Это просто перебирает все возможности от 1 до 1 << 30. Он огромный, медленный, я даже не знаю, работает ли он правильно, но он буквально соответствует спецификациям, так как проверяет состояние каждый раз, так что это хорошо. Я не проверял это, потому что у ideone есть 5-секундный лимит времени для программ, и поэтому он не завершится.

(На случай, если кому-то интересно: это колоссальные 308 байт )

static double[]f(double n)
{
    for(double x=1;x<1<<30;x++)
    {
        for(double y=1;y<1<<30;y++)
        {
            for(double z=1;z<1<<30;z++)
            {
                if(4/n==1/x+1/y+1/z)
                    return new[]{x,y,z};
            }
        }
    }
    return null;
}

Обновление: исправлено, так что на самом деле работает


2
Не работает (подсказка: целочисленное деление).
Говард

Вероятно, это не сработает из-за ошибок округления.
Сомниум

@ user2992539 это работает для меня, я проверил его в 5качестве ввода, и он дал правильный результат ( 2, 4, 20)
Кристоф Бемвальдер

@HackerCow это может не работать для больших целых чисел.
Сомниум

1
@HackerCow вы, безусловно, можете сэкономить время, начав с y = x + 1 и z = y + 1. Вероятно, будет быстрее использовать эквивалентную проверку 4xyz = n (xy + yz + xz), хотя я принимаю, что это более длинное выражение и также есть проблемы с округлением.
Алхимик

3

Python 2 , 171 байт

from sympy import*
def f(n):
 for d in xrange(1,n*n):
  for p in divisors(4*d+n*n):
   q=(4*d+n*n)/p;x=(n+p)/4;y=(n+q)/4
   if (n+p)%4+(n+q)%4+n*x*y%d<1:return x,y,n*x*y/d

Попробуйте онлайн!

Первый ответ достаточно быстр, чтобы быть исчерпывающим. Это позволяет находить решения для всех 3 ≤ n ≤ 1000000 всего за 24 минуты , в среднем около 1,4 миллисекунд каждая.

Как это устроено

Перепишите 4 / n = 1 / x + 1 / y + 1 / z как z = n · x · y / d , где d = 4 · x · y - n · x - n · y . Тогда мы можем множить 4 · d + n 2 = (4 · x - n ) · (4 · y - n ), что дает нам гораздо более быстрый способ поиска x и y до тех пор, пока dмаленький. С учетом х < у < г , мы можем по крайней мере доказать , d <3 · п 2 /4 (следовательно, граница внешнего цикла), хотя на практике она имеет тенденцию быть намного меньше-95% времени, мы можем использовать д = 1, 2 или 3. Наихудший случай - n = 769129, для которого наименьшее d - 1754 (этот случай занимает около 1 секунды).


1

Mathematica, 99 байт

f[n_]:=(x=1;(w=While)[1>0,y=1;w[y<=x,z=1;w[z<=y,If[4/n==1/x+1/y+1/z,Return@{x,y,z}];++z];++y];++x])

Это довольно наивная грубая сила, поэтому она не очень хорошо масштабируется. Я определенно собираюсь получить миллион (так что не стесняйтесь пока считать это недействительным). n = 100занимает полсекунды, но n = 300уже занимает 12 секунд.


1

Golflua 75

Читает nиз приглашения (после вызова в терминале), но в основном выполняет итерации, как это делает решение Calvin's Hobbies :

n=I.r()z=1@1~@y=1,z-1~@x=1,y-1?4*x*y*z==n*(y*z+x*z+x*y)w(n,x,y,z)~$$$z=z+1$

Необузданная версия Lua выше

n=io.read()
z=1
while 1 do
   for y=1,z-1 do
      for x=1,y-1 do
         if 4*x*y*z==n*(y*z+x*z+x*y) then
            print(n,x,y,z)
            return
         end
      end
   end
   z=z+1
end

Примеры:

n=6     -->     3      4     12
n=12    -->     6     10     15
n=100   -->    60     75    100
n=1600  -->  1176   1200   1225

1

Питон, 117

n=input();r=range;z=0
while 1:
 z+=1
 for y in r(z):
  for x in r(y):
    if 4*x*y*z==n*(y*z+x*z+x*y):print x,y,z;exit()

Пример:

16 --> 10 12 15

Ничего особенного.


1
Почему вы определяете функцию, если вы собираетесь вызывать ее только один раз?
Исаак

@isaacg Это нужно как-то остановить, но использование exit()вместо этого сокращает его.
Увлечения Кэлвина

0

C # - 134

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

Он вычисляет все примеры технически правильно (я не пробовал последние два, потому что, опять же, ideone сообщает ограничение по времени в 5 секунд), но первые дают правильный результат (не обязательно результат, который вы рассчитали, но правильный). Это странно выводит номер из строя (я понятия не имею , почему) , и это дает 10, 5, 2для 5(что является правильным ответом , согласно википедии).

134 байта на данный момент, я мог бы, вероятно, увеличить его немного.

float[]f(float n){float x=1,y,z;for(;x<1<<30;x++)for(y=1;y<x;y++)for(z=1;z<y;z++)if(4/n==1/x+1/y+1/z)return new[]{x,y,z};return null;}

0

Хаскель - 150 символов

main = getLine >>= \n -> (return $ head $ [(x,y,z) | x <- [1..y], y <- [1..z], z <- [1..], (4/n') == (1/x) + (1/y) + (1/z)]) where n' = read n

Это должно сработать, но я еще не скомпилировал. Это почти наверняка очень, очень медленно. Он проверяет каждую возможную тройку действительных целых чисел и должен остановиться, когда увидит работающий набор.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.