Files

3.3 KiB
Raw Permalink Blame History

id, title, challengeType, forumTopicId, dashedName
id title challengeType forumTopicId dashedName
5900f3ae1000cf542c50fec1 Завдання 66: Діофантове рівняння 5 302178 problem-66-diophantine-equation

--description--

Розглянемо квадратні діофантові рівняння типу:

x2 Dy2 = 1

Наприклад, для D=13, мінімальний розв'язок х дорівнює 6492 13×1802 = 1.

Можна припустити, що розв'язків у додатних числах не існує, якщо D дорівнює квадрату цілого числа.

Знайшовши мінімальні розв’язки x для D = {2, 3, 5, 6, 7}, отримаємо наступне:

32 2×22 = 1
22 3×12 = 1
92 5×42 = 1
52 6×22 = 1
82 7×32 = 1

Отже, беручи до уваги мінімальні розв'язки x для D ≤ 7, найбільший x отримаємо тоді, коли D=5.

Знайдіть значення D ≤ n у мінімальних розв'язках x, для яких отримано найбільше значення x.

--hints--

diophantineEquation(7) має повернути число.

assert(typeof diophantineEquation(7) === 'number');

diophantineEquation(7) має повернути 5.

assert.strictEqual(diophantineEquation(7), 5);

diophantineEquation(100) має повернути 61.

assert.strictEqual(diophantineEquation(100), 61);

diophantineEquation(409) має повернути 409.

assert.strictEqual(diophantineEquation(409), 409);

diophantineEquation(500) має повернути 421.

assert.strictEqual(diophantineEquation(500), 421);

diophantineEquation(1000) має повернути 661.

assert.strictEqual(diophantineEquation(1000), 661);

--seed--

--seed-contents--

function diophantineEquation(n) {

  return true;
}

diophantineEquation(7);

--solutions--

function diophantineEquation(n) {
  // Based on https://www.mathblog.dk/project-euler-66-diophantine-equation/
  function isSolution(D, numerator, denominator) {
    return numerator * numerator - BigInt(D) * denominator * denominator === 1n;
  }

  let result = 0;
  let biggestX = 0;

  for (let D = 2; D <= n; D++) {
    let boundary = Math.floor(Math.sqrt(D));
    if (boundary ** 2 === D) {
      continue;
    }

    let m = 0n;
    let d = 1n;
    let a = BigInt(boundary);

    let [numerator, prevNumerator] = [a, 1n];

    let [denominator, prevDenominator] = [1n, 0n];

    while (!isSolution(D, numerator, denominator)) {
      m = d * a - m;
      d = (BigInt(D) - m * m) / d;
      a = (BigInt(boundary) + m) / d;

      [numerator, prevNumerator] = [a * numerator + prevNumerator, numerator];
      [denominator, prevDenominator] = [
        a * denominator + prevDenominator,
        denominator
      ];
    }

    if (numerator > biggestX) {
      biggestX = numerator;
      result = D;
    }
  }
  return result;
}