Главная
Регистрация
Вход
Воскресенье
28.04.2024
21:34
Приветствую Вас Гость | RSS

Сайт учителя информатики  

Тиньковой Елены Николаевны  


Меню сайта

Ученикам

Учителю

Категории раздела
В помощь ученику [8]
Школьные задания [14]
информация [42]
инф

Наш опрос
Оцените мой сайт
Всего ответов: 216

 6 задача 

 

Пояснение к примеру

 

В приведенном примере Андрей сможет показать следующие варианты счета: 1:1:2, 1:2:1, 2:1:1, 1:2:2, 2:1:2, 2:2:1, 2:2:3, 2:3:2, 3:2:2. Другие тройки чисел, которые можно составить с использованием имеющихся карточек, не удовлетворяют заданному условию, что баллы любых двух игроков различаются не более чем в k = 2 раза.

 

 Рассмотрим три случая: все три игрока набрали равное число баллов, все три игрока набрали попарно различное число баллов, либо два игрока из трех набрали равное число баллов, а у третьего количество баллов отлично от двух других.

 

Научимся находить количество вариантов счета в каждом из трех случаев, тогда получившиеся значения необходимо сложить. Отметим, что в подзадаче 1 выполнено условие, что k = 1, и, следовательно, имеет место только первый случай, а в подзадаче 3 все числа различны, и, следовательно, имеет место только второй случай. Этим можно воспользоваться для написания частичных решений для этих подзадач.

 

Поместим входные данные в массив и отсортируем его. Одним проходом по получившемуся массиву заменим числа на пары (xi, ci), где ci – количество раз, которое значение xi встречается на карточках у Андрея, xi во всех парах различны. Заметим, что массив пар получился отсортированным по по xi.

 

    cin >> n >> k;

    vector<long long> x(n);

    for (int i = 0; i < n; i++) {

        cin >> x[i];

    }

 

    sort(x.begin(), x.end()); 

 

    vector<pair<long long, int>> p;

    int pr = -1;

    for (int i = 0; i < n; i++) {

        if (i == n - 1 || x[i] != x[i + 1]) {

            p.push_back({x[i], i - pr});

            pr = i;

        }

    }

 

    int m = p.size(); 

 

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

 

Ниже приведен код на Си++, который считает число таких вариантов.

 

    long long ans1 = 0;

    for (int i = 0; i < m; i++) {

        if (p[i].second >= 3) {

            ans1++;

        }

    }

Для определения числа вариантов в остальных двух случаях требуется применить метод двух указателей. Для определения количества вариантов счета, в котором баллы всех игроков различны, сделаем следующее. Для каждого варианта максимального из баллов трех игроков найдем минимальное значение баллов другого игрока, которое можно показать, и оно не нарушает условия, что баллы различаются не более чем в k раз. Пусть для максимального значения xi соответствующее минимальное значение xj. Тогда два других значения баллов можно выбрать среди значений xj, xj+1,…, xj–1, то есть существует
(
ij)(ij – 1) / 2 способов это сделать. Поскольку 3 различных числа можно упорядочить 6 способами, это число необходимо умножить на 6.

 

Просуммируем эти значения по всем i. Заметим, что при увеличении i значение j также может только увеличиваться, поэтому проход занимает O(n).

 

Приведем код на Си++, который подсчитывает это число вариантов.

 

    long long ans2 = 0;

    int j = 0;

    for (int i = 0; i < m; i++) {

        while (j < i && p[j].first * k < p[i].first) {

            j++;

        }

        ans2 += 6LL * (i - j) * (i - j - 1) / 2;

    }

Наконец, аналогичный метод применим для подсчета количества вариантов счета, когда два игрока набрали равное количество баллов, а третий игрок набрал отличное от них количество баллов.

 

    long long ans3 = 0;

    j = 0;

    for (int i = 1; i < m; i++) {

        while (j < i && p[j].first * k < p[i].first) {

            j++;

        }

        if (p[i].second > 1) {

            ans3 += 3 * (i - j);

        }

    }

    j = m - 1;

    for (int i = m - 2; i >= 0; i--) {

        while (j > i && p[i].first * k < p[j].first) {

            j--;

        }

        if (p[i].second > 1) {

            ans3 += 3 * (j - i);

        }

    }

Для решения подзадачи 1 достаточно рассмотреть вариант, что у всех игроков одинаковое число баллов. Отметим, что дополнительное ограничение 1 ≤ xi ≤ 100 000 позволяет обойтись без сортировки пар или сложных структур данных и запоминать количество карточек с каждым числом в массиве.

 

Для решения подзадачи 2 можно перебрать все тройки карточек, для каждого варианта счета в трехмерном массиве отметить, можно ли получить этот счет, и вывести количество вариантов, которое можно получить.

Для решения подзадачи 3 требуется реализовать описанное выше решение, но не требуется разбирать случай, когда два игрока набрали равное число баллов.


Вход на сайт

Портфолио

Кабинет

Достижения

Поиск

Календарь
«  Апрель 2024  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930

Друзья сайта

Бахмутова Е.Н.

Киреева Т.В.

Вахрамеева Л.Н.

Карабухина Н.П.

Тинькова Е.Н.

Горелова В.А.


Сайт существует

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Всего на сайте
Total users: 425

Copyright MyCorp © 2024
Конструктор сайтов - uCoz