Подсчитайте количество правильных дробей

Фракция p/q (p и q - положительные целые числа) является правильной, если p/q < 1. Учитывая 3 <= N <= 50 000 000, напишите программу для подсчета количества правильных дробей p / q, таких что p + q = n, а p, q - относительные простые числа (их наибольший общий делитель - 1). Это мой код

bool prime_pairs(int x, int y) {
    int t = 0;
    while (y != 0) {
        t = y;
        y = x % y;
        x = t;
    }
    return (x == 1);
}

void proer_fractions(int n) {
    int num = n % 2 == 0 ? n / 2 - 1 : n / 2, den = 0, count = 0;
    for (; num > 0; --num) {
        den = n - num;
        if (prime_pairs(num, den))
            ++count;
    }
    printf("%d", count);
}

Интересно, правильно ли я это сделал. Есть ли способ ускорить алгоритм? Моему ноутбуку (i7-4700mq) потребовалось 2,97 секунды для запуска в режиме выпуска, когда N = 50 000 000.

Большое спасибо.

1 ответ

Решение

Ключевым фактом является то, что если p + q = n а также gcd(p, q) = k тогда k должно делить n. И наоборот, если p взаимно прост с n, то q = n - p должно быть взаимно с р.

Следовательно, проблема подсчета взаимно простых пар (p, q), которые суммируются с n, эффективно сводится к подсчету чисел, взаимно простых с n ( число Эйлера, aka phi) и делению этого числа на 2.

В сети есть много кода для вычисления коэффициента числа, например, в статье Toeent Function Эйлера в статье GeeksForGeeks. По сути, это сводится к факторизации числа, которое должно быть немного быстрее, чем ваш текущий алгоритм (около 5 порядков). Повеселись!

Другие вопросы по тегам