Может ли кто-нибудь объяснить мне этот код интуитивно (нахождение nCr без ошибки переполнения)?

https://www.geeksforgeeks.org/program-to-calculate-the-value-of-ncr-efficiently/

это код, который я хочу понять. Вот видео, которое объясняет это более подробно https://thewikihow.com/video_lhXwT7Zm3EU -> однако я до сих пор не понимаю определенного аспекта этого. Вот код:


// Java implementation to find nCr
 
class GFG {
 
    // Function to find the nCr
    static void printNcR(int n, int r)
    {
 
        // p holds the value of n*(n-1)*(n-2)...,
        // k holds the value of r*(r-1)...
        long p = 1, k = 1;
 
        // C(n, r) == C(n, n-r),
        // choosing the smaller value
        if (n - r < r) {
            r = n - r;
        }
 
        if (r != 0) {
            while (r > 0) {
                p *= n;
                k *= r;
 
                // gcd of p, k
                long m = __gcd(p, k);
 
                // dividing by gcd, to simplify
                // product division by their gcd 
                // saves from the overflow
                p /= m;
                k /= m;
 
                n--;
                r--;
            }
 
            // k should be simplified to 1
            // as C(n, r) is a natural number
            // (denominator should be 1 ) .
        }
        else {
            p = 1;
        }
 
        // if our approach is correct p = ans and k =1
        System.out.println(p);
    }
 
    static long __gcd(long n1, long n2)
    {
        long gcd = 1;
 
        for (int i = 1; i <= n1 && i <= n2; ++i) {
            // Checks if i is factor of both integers
            if (n1 % i == 0 && n2 % i == 0) {
                gcd = i;
            }
        }
        return gcd;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 50, r = 25;
 
        printNcR(n, r);
    }
}

В частности, почему этот код работает:

if (n - r < r)
  r = n - r;

Почему, выполняя эту простую операцию, в конечном итоге выдает правильный ответ после прохождения и выхода из основного цикла while? Я не понимаю, зачем это нужно и почему это имеет смысл делать. Например, почему без этого кода расчет nCr не работает или не работает так, как задумано???? Если кто-то может объяснить это или указать мне где-нибудь, где это объясняется, или математическая концепция, или что-то еще, это было бы здорово :) Может быть, помог бы другой способ кодирования того же самого. Я просто хочу понять, почему это дает правильный ответ для студента, изучающего математику и программирование. Чтобы дать некоторое представление о моих способностях (чтобы вы знали, на каком я уровне), я изучаю объектно-ориентированное программирование и закончил среднюю школу по математике и основам информатики. Я ни в коем случае не эксперт.

По сравнению с чем? Конечно, более важным вопросом является... почему какой-то другой метод расчета дает неверные результаты.

Dawood ibn Kareem 16.12.2020 05:55
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
124
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У операции nCr есть особенность, и она упоминается в комментарии над условием if: // C(n, r) == C(n, n-r). Теперь цикл while повторяется, когда r>0, и с каждой итерацией значение r уменьшается на 1. Таким образом, чтобы уменьшить количество выполнений цикла, нам нужно уменьшить значение r (если возможно). Поскольку C(n, r) == C(n, n-r), мы берем меньшее значение из r и n-r, чтобы количество итераций было минимальным, но результат оставался прежним.

Предположим, что n = 100 и r=99. В этом случае, если мы пропустим условие if, то цикл будет выполнен 99 раз, тогда как с помощью условия if мы можем обновить r как r = n-r, чтобы r=1, тогда цикл был бы выполнен только один раз. Таким образом мы спасаем 98 нежелательные итерации.

Таким образом, если мы включим условие if, производительность значительно улучшится.

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