YAPTCHA#5730

YAPTCHA (Розбір)

Нехай m = 3k + 7. Тоді шуканий вираз перепишеться у вигляді:

S_n = \sum_{m = 10, m = 1~(mod~3)}^{3n + 7} \left\lfloor \frac{(m - 1)! + 1}{m} - \left\lfloor \frac{(m - 1)!}{m} \right\rfloor \right\rfloor,

Теорема Вільсона. Якщо — просте число, то

(m - 1)! = -1~(mod~m)

Тобто

(m - 1)! + 1 = 0~(mod~m)

Таким чином, якщо — просте число, то число \frac{(m-1)!+1}{m} буде цілим.

У той час

\left\lfloor \frac{(m-1)!}{m} \right\rfloor = \left\lfloor \frac{(m - 1)! + 1}{m} - \frac{1}{m} \right\rfloor = \frac{(m - 1)! + 1}{m} - 1

Тоді весь вираз дорівнює

\left\lfloor \frac{(m - 1)! + 1}{m} - \left\lfloor \frac{(m - 1)!}{m} \right\rfloor \right\rfloor = \frac{(m - 1)! + 1}{m} - \left( \frac{(m - 1)! + 1}{м} - 1 \right) = 1

Якщо — складене число, то

(m - 1)! = 0~(mod~m),

оскільки серед множників зліва є всі дільники числа .

У цьому випадку число

\frac{(m-1)!}{m}

буде цілим.

Тоді весь вираз дорівнює

\left\lfloor \frac{(m - 1)! + 1}{m} - \left\lfloor \frac{(m - 1)!}{m} \right\rfloor \right\rfloor = \left\lfloor \frac{(m - 1)!}{m} + \frac{1}{m} - \frac{(m - 1)!}{m} \right\rfloor = \left\lfloor \frac{1}{m} \right\rfloor = 0

Щоб обчислити S_n, достатньо порахувати кількість простих чисел виду 3k + 7 при 1 \le k \le n.

За допомогою решета Ератосфена будуємо масив , в якому:

used[i] = \begin{cases} 1, & \text{якщо } i \text{ просте}, \\ 0, & \text{якщо } i \text{ складене}. \end{cases}

Далі, використовуючи масив , будуємо масив , який містить інформацію про прості числа виду 3i + 7:

a[i] = \begin{cases} 1, & \text{якщо } 3i + 7 \text{ просте}, \\ 0, & \text{якщо } 3i + 7 \text{ складене}. \end{cases}

Тепер

S_n = a[1] + a[2] + … + a[n]

Оскільки в задачі є багато тестів, щоб відповідати на них за константний час, побудуємо префіксні суми:

p[i] = a[1] + a[2] + … + a[i]

Тепер для відповіді на задачу для кожного значення достатньо вивести .

Приклад

Нехай m = 7 — просте. Тоді

\left\lfloor \frac{6!+1}{7} - \left\lfloor \frac{6!}{7} \right\rfloor \right\rfloor = \left\lfloor \frac{721}{7} - \left\lfloor \frac{720}{7} \right\rfloor \right\rfloor = \left\lfloor 103 - \left\lfloor 102 \frac{6}{7} \right\rfloor \right\rfloor = \left\lfloor 103 - 102 \right\rfloor = 1

Нехай m = 6 — складене. Тоді

\left\lfloor \frac{5!+1}{6} - \left\lfloor \frac{5!}{6} \right\rfloor \right\rfloor = \left\lfloor \frac{121}{6} - \left\lfloor \frac{120}{6} \right\rfloor \right\rfloor = \left\lfloor 20 + \frac{1}{6} - 20 \right\rfloor = \left\lfloor \frac{1}{6} \right\rfloor = 0

Обчислимо відповідь для n = 10. Розглянемо всі числа виду 3k + 7, де 1 \le k \le 10. Виділимо серед них прості.

Серед перелічених чисел є простих числа: та . Отже, S_{10} = 4.

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

Оголосимо робочі масиви. Оскільки n \le 10^6, розмір масивів слід встановити рівним 3n + 7 = 3 \cdot 10^6 + 7.

#define MAX 3000010
char used[MAX], a[MAX];

Функція Init реалізує решето Ератосфена. Масив містить інформацію про прості числа:

used[i] = \begin{cases} 1, & \text{якщо } i \text{ просте}, \\ 0, & \text{якщо } i \text{ складене}. \end{cases}

Масив містить інформацію про прості числа виду 3i + 7:

a[i] = \begin{cases} 1, & \text{якщо } 3i + 7 \text{ просте}, \\ 0, & \text{якщо } 3i + 7 \text{ складене}. \end{cases}
void Init()
{
  for (int i = 2; i < MAX; i++)
  {
    if (!used[i])
    {
      if ((i - 7) % 3 == 0)
        a[(i - 7) / 3] = true;
      if (i < sqrt(MAX))
        for (int j = i * i; j < MAX; j += i)
          used[j] = true;
    }
  }
}

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

Init();

Обчислюємо префіксні суми для масиву :

p[i] = a_1 + a_2 + ... + a_i
for (int i = 2; i < MAX; ++i)
  p[i] = p[i - 1] + a[i];

Послідовно обробляємо тестів.

scanf("%d", &tests);
while (tests--)
{
  scanf("%d", &n);

Для кожного значення виводимо .

  printf("%d\n", p[n]);
}