Екстремум Ейлера#4107

Екстремум Ейлера (Розбір)

Перепишемо вказану суму наступним чином:

φ(1) \cdot φ(1) + φ(1) \cdot φ(2) + ... + φ(1) \cdot φ(n) + \\ φ(2) \cdot φ(1) + φ(2) \cdot φ(2) + ... + φ(2) \cdot φ(n) + \\ . . . \\ φ(n) \cdot φ(1) + φ(n) \cdot φ(2) + ... + φ(n) \cdot φ(n)

Згрупуємо доданки в сумі за спільним множником:

φ(1) \cdot (φ(1) + φ(2) + … φ(n)) + \\ φ(2) \cdot (φ(1) + φ(2) + … φ(n)) + \\ . . . \\ φ(n) \cdot (φ(1) + φ(2) + … φ(n))

У всіх доданках присутній один і той самий множник. Винесемо його за дужки:

H = (φ(1) + φ(2) + … φ(n))^2

Реалізуємо решето, яке обчислить всі значення функції Ейлера від до 10^4 і збереже їх у масиві . Потім побудуємо масив часткових сум , де

sum[i] = φ(1) + φ(2) + ... + φ(i)

Після цього для кожного вхідного значення виведемо добуток

sum[n] \cdot sum[n]

Приклад

Розглянемо стан масиву значень функції Ейлера та масиву часткових сум :

Для n = 10 відповідь дорівнює

(φ(1) + φ(2) + … φ(10))^2 = sum[10]^2 = 32^2 = 1024

Реалізація алгоритму

Оголосимо робочі масиви та , де

#define MAX 10001
long long fi[MAX], sum[MAX];

Функція FillEuler заповнює масив значеннями функції Ейлера:

fi[i] = φ(i)~для~всіх~1 ≤ i \u003c MAX
void FillEuler(void)
{
  int i, j;
  for (i = 0; i \u003c MAX; i++) fi[i] = i;
  for (i = 2; i \u003c MAX; i++)
    if (fi[i] == i)
      for (j = i; j \u003c MAX; j += i)
        fi[j] -= fi[j] / i;

Обчислюємо часткові суми . Ініціалізуємо перші елементи масиву.

  sum[0] = 0; sum[1] = 1;

Потім послідовно обчислюємо решту часткових сум.

  for(i = 2; i \u003c MAX; i++)
    sum[i] = sum[i-1] + fi[i];
}

Основна частина програми. Заповнюємо масиви та .

FillEuler();

Обробляємо тестів.

scanf("%d",\u0026tests);
while(tests--)
{
  scanf("%d",\u0026n);

Для кожного вхідного значення обчислюємо і виводимо відповідь

sum[n] \cdot sum[n] = (φ(1) + φ(2) + … φ(n))^2
  res = sum[n] * sum[n];
  printf("%lld\n",res);
}