Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/120: Рейтинг темы: голосов - 120, средняя оценка - 4.63
0 / 0 / 0
Регистрация: 28.11.2018
Сообщений: 37
1

Подсчитать количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает с порядковым номером действия

18.12.2018, 00:17. Показов 25091. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Из урны с 10 пронумерованными шариками вынимают по одному шарику. Подсчитать общее количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает с порядковым номером действия "вынимания", например, когда шарик № 3 будет вынут 3-им по порядку.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.12.2018, 00:17
Ответы с готовыми решениями:

Подсчитать общее количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает с порядковым номером действия
Помогите составить программу по задачке. Очень важно с комментариями, без них не пойму. PS:...

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

Найти элементы массива, в которых значение совпадает с порядковым номером и подсчитать их количество
#include <iostream> #include <cmath> #include <iomanip> using namespace std; int main(void) {...

Найдите вероятность того, что хотя бы при одном извлечении номер шара совпадает с номером опыта
В урне имеется n одинаковых шаров с номерами от 1 до n. Шары извлекаются по одному без возвращения....

13
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
18.12.2018, 00:42 2
Hell Diablo, обычная комбинаторика, ни чего сложного
0
119 / 94 / 35
Регистрация: 18.12.2012
Сообщений: 654
18.12.2018, 02:16 3
Цитата Сообщение от Hell Diablo Посмотреть сообщение
Подсчитать общее количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает с порядковым номером действия "вынимания"
А чё их считать ? Их будет 10.
На каждый из 10-ти шариков может попасть только 1 "вынимание", удовлетворяющее условие задачи.
0
Параллельный Кот
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
18.12.2018, 02:37 4
Цитата Сообщение от alkl Посмотреть сообщение
А чё их считать ? Их будет 10.
Уверены? Ситуация - это последовательность из 10 номеров шаров, записанных в порядке извлечения из мешка. И любая такая последовательность, в которой хотя бы одно из чисел совпадает с номером шага, будет подходящей.
0
119 / 94 / 35
Регистрация: 18.12.2012
Сообщений: 654
18.12.2018, 02:54 5
Цитата Сообщение от valen10 Посмотреть сообщение
Ситуация - это последовательность из 10 номеров шаров, .....
Если это так, то
Цитата Сообщение от valen10 Посмотреть сообщение
Уверены?
уже нет

Почему то подумал, что ТС назвал ситуацией - совпадение номеров.
Цитата Сообщение от Hell Diablo Посмотреть сообщение
общее количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает ...
Т.е., судя по тексту, логично предположить, что "ситуация" - это совпадение. И нужно подсчитать кол-во этих ситуаций.

Добавлено через 7 минут
В общем, опять очередные догадки и тишина от ТС. Пусть разруливает эту ситуацию - нормально опишет условие.
0
Параллельный Кот
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
18.12.2018, 03:18 6
Долго пытался вывести формулу, но что-то не могу сообразить, программу написать проще. Проверяйте, надеюсь правильная. Для N=10 результат получается 2293839.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
 
unsigned factorial(unsigned n) {
    return ((n > 1) ? n * factorial(n - 1) : n);
}
 
unsigned getMismatchCount(bool select[], unsigned n, unsigned step = 0) {
    unsigned count = 0;
    if (step >= n) {
        count = 1;
    }
    else {
        for (unsigned i = 0; i < n; i++) {
            if ((i != step) && !select[i]) {
                select[i] = true;
                count += getMismatchCount(select, n, step + 1);
                select[i] = false;
            }
        }
    }
 
    return count;
}
 
int main() {
    const unsigned N = 10;
    bool select[N];
 
    for (auto &f : select) {
        f = false;
    }
 
    cout << factorial(N) - getMismatchCount(select, N) << endl;
 
    return 0;
}
0
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
18.12.2018, 08:54 7
valen10, Мне кажется, что ответ будет факториал девяти + 1
Поясню: Сколькими способами мы можем вытащить любой шар - 10-ю, а сколькими способами можно вытащить первый шар, так как это первое действие, только одним, значит 1 +
далее нас не интересуют уже порядок, значит + факториал девяти
0
Параллельный Кот
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
18.12.2018, 09:10 8
Avaddon74, хорошо бы, если было так просто. Но условие говорит о любом хотя бы одном совпадении. Пусть первый шар не совпал, тогда может совпасть второй, третий и т.д., а для них считать количество подходящих случаев уже сложнее.

Свои догадки проверял на случае n=4, для которого можно без труда выписать все перестановки и отметить подходящие. Всего 4!=24, подходящих 15. Проверим вашу гипотезу: (n - 1)! + 1 =3! + 1 = 7, меньше чем нужно.

Исходя из того, что проще посчитать неподходящие случаи, вычел из количества всех перестановок количество неподходящих. Было бы здорово формулу придумать, но у меня не вышло. Сомнения в успехе поиска формулы вызывает тот факт, что задачу предлагается решить именно программой. Могу быть не прав.
1
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
18.12.2018, 10:22 9
valen10, Да, я не прав, но и у вас ошибка, число комбинаций при n = 4 16

Добавлено через 1 минуту
1234
1324
1243
1342
1423
1432
2134
2314
2431
3214
3241
3124
3214
4213
4231
4132

Добавлено через 1 минуту
Поторопился я с первой формулой, щас, нужно подумать
0
Параллельный Кот
1905 / 827 / 350
Регистрация: 25.03.2016
Сообщений: 2,045
18.12.2018, 15:13 10
Avaddon74, Вы были невнимательны У вас есть повтор.

1234
1324
1243
1342
1423
1432
2134
2314
2431
3214
3241
3124
3214
4213
4231
4132

Добавлено через 6 минут
Попробуйте решать обратную задачу - вычисление количества неподходящих перестановок. Их количество меньше и, возможно, вычислить его будет проще.

Добавлено через 4 часа 39 минут
Avaddon74, если Вы еще не отчаялись найти формулу, у меня есть хорошие новости. Ваши рассуждения натолкнули на мысль, как подойти к решению с другой стороны. Если желаете самостоятельно найти решение, не читайте написанное под спойлером.

(1) Получается, что если на шаге https://www.cyberforum.ru/cgi-bin/latex.cgi?step_k есть совпадение номеров, тогда результаты следующих шагов уже не важны, их (независимо от результатов совпадения) будет (n - k)!, все они будут подходящими и должны быть прибавлены к конечному результату.
(2) Т.к. на шаге https://www.cyberforum.ru/cgi-bin/latex.cgi?step_k будут учтены всевозможные исходы испытаний последующих шагов, можно утверждать, что шаг https://www.cyberforum.ru/cgi-bin/latex.cgi?step_k учитывает всевозможные результаты для шагов с номерами k < j <= n.
(3) На предыдущих шагах не может быть совпадений, поскольку такая ситуация уже была учтена ранее.
(4) Если на шаге https://www.cyberforum.ru/cgi-bin/latex.cgi?step_k нет совпадения, счет продолжается для следующих шагов.

Эти рассуждения позволяют перейти от счета несовпадений к счету совпадений, что уже ближе к вопросу задачи.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
unsigned getSuitableCount(bool select[], unsigned n, unsigned step_k = 1) {
    unsigned count = 0;
    if (step_k <= n) {
        for (unsigned i = 1; i <= n; i++) {
            if (!select[i - 1]) { // Совпадение номеров шара и шага.
                if (i == step_k) { // Номер шара совпадает с номером шага.
                    // Слева совпадений быть не может.
                    // Справа, независимо от наличия там совпадений,
                    // возможно (n - k)! перестановок.
                    count += factorial(n - step_k);
                }
                else { // Нет совпадения номеров.
                    // Отмечаем текущий номер шара как извлеченный.
                    select[i - 1] = true;
 
                    // Для извлеченного на данном шаре шара № i
                    // получаем количество подходящих перестановок
                    // на следующих k < j <= n шагах.
                    count += getSuitableCount(select, n, step_k + 1);
 
                    // Возврат шара обратно.
                    select[i - 1] = false;
                }
            }
        }
    }
    else {
        // Совпадений для несуществующего k > n быть не может.
        // count = 0;
    }
 
    return count;
}
Получился тот же перебор с отсечениями и сложностью https://www.cyberforum.ru/cgi-bin/latex.cgi?O(n!). Изменения только косметические, не влияющие ни на результат, ни на скорость его получения. Однако от этого варианта решения к формуле всего 1 вопрос и 1 шаг.

Рекурентная формула для вычисления количества перестановок

Получается, что при условии отсутствия совпадений на предыдущих шагах, для шага k можно быстро вычислить количество подходящих перестановок. Но эти вычисления будут многократно повторяться для всевозможных комбинаций несовпадения номеров на предыдущих шагах. Нельзя ли количество этих несовпадений тоже вычислить и умножить на результат текущего шага?

(1) Допустим, на всех шагах с номерами [k, k + 1, ..., n] есть совпадение, на предыдущих шагах совпадений нет. Тогда число таких перестановок равно количеству несовпадений из (n - k) номеров.
(2) Если на m из n шагов было совпадение, то расстановка остальных номеров не имеет значения (главное, чтобы там не было совпадений, чтобы не изменилось число m), количество таких перестановок равно количеству несовпадений из (n - m) номеров.
(3) Количество различных способов выбрать m номеров c совпадениями из n возможных равно https://www.cyberforum.ru/cgi-bin/latex.cgi?C_{n}^{m}.
(4) Умножая количество сочетаний совпадающих номеров на количество несовпадений на остальных шагах получим общее количество перестановок для m совпадений из n номеров.
(5) Общее количество подходящих перестановок равно сумме перестановок по m совпадений из n чисел для 1 <= m <= n.
(6) Количество несовпадений находится вычитанием количества совпадений из общего числа перестановок.
(7) Решения задачи для n сводится к решению задачи для n - 1 c целью вычисления количества несовпадений для (n - 1) чисел.

Итоговые формулы:
https://www.cyberforum.ru/cgi-bin/latex.cgi?S_0 = 0
https://www.cyberforum.ru/cgi-bin/latex.cgi?U_0 = 1
https://www.cyberforum.ru/cgi-bin/latex.cgi?S_n = \sum_{i = 1}^{n} C_{n}^{i} \cdot U_{n - i}
https://www.cyberforum.ru/cgi-bin/latex.cgi?U_n = n! - S_n

Это позволяет перейти от порядка роста функции https://www.cyberforum.ru/cgi-bin/latex.cgi?O(n!) к https://www.cyberforum.ru/cgi-bin/latex.cgi?O(n^2).

Итоговая программа с тремя способами решения и подсчетом количества вычислений
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <vector>
using namespace std;
 
static unsigned funcUnsuitableTotalCount = 0;
static unsigned funcSuitableTotalCount = 0;
static unsigned funcRecurrentTotalCount = 0;
 
unsigned factorial(unsigned n) {
    static vector<unsigned> saved;
 
    if (saved.size() < n + 1) {
        saved.resize(n + 1, 0);
    }
 
    if (saved[n] == 0) {
        saved[n] = ((n > 1) ? n * factorial(n - 1) : 1);
    }
 
    return saved[n];
}
 
/**
 * Подсчет количества перестановок без совпадений.
 */
unsigned getUnsuitableCount(bool select[], unsigned n, unsigned step_k = 1) {
    // === Количество вызовов функции ==================
    funcUnsuitableTotalCount++;
    // =================================================
 
    unsigned count = 0;
    if (step_k <= n) {
        for (unsigned i = 1; i <= n; i++) {
            if ((i != step_k) && !select[i - 1]) {
                select[i - 1] = true;
                count += getUnsuitableCount(select, n, step_k + 1);
                select[i - 1] = false;
            }
        }
    }
    else {
        // Количество несовпадений для несуществующего k > n искусственно
        // принимается равным 1.
        count = 1;
    }
 
    return count;
}
 
/**
 * Подсчет количества перестановок с хотя бы одним совпадением.
 */
unsigned getSuitableCount(bool select[], unsigned n, unsigned step_k = 1) {
    // === Количество вызовов функции ==================
    funcSuitableTotalCount++;
    // =================================================
 
    unsigned count = 0;
    if (step_k <= n) {
        for (unsigned i = 1; i <= n; i++) {
            if (!select[i - 1]) { // Совпадение номеров шара и шага.
                if (i == step_k) { // Номер шара совпадает с номером шага.
                    // Слева совпадений быть не может.
                    // Справа, независимо от наличия там совпадений,
                    // возможно (n - k)! перестановок.
                    count += factorial(n - step_k);
                }
                else { // Нет совпадения номеров.
                    // Отмечаем текущий номер шара как извлеченный.
                    select[i - 1] = true;
 
                    // Для извлеченного на данном шаре шара № i
                    // получаем количество подходящих перестановок
                    // на следующих k < j <= n шагах.
                    count += getSuitableCount(select, n, step_k + 1);
 
                    // Возврат шара обратно.
                    select[i - 1] = false;
                }
            }
        }
    }
    else {
        // Совпадений для несуществующего k > n быть не может.
        // count = 0;
    }
 
    return count;
}
 
/**
 * Количество сочетаний из n по k.
 */
unsigned C(unsigned n, unsigned k) {
    return factorial(n) / factorial(k) / factorial(n - k);
}
 
/**
 * Вычисление количества перестановок с хотя бы одним совпадением
 * по рекурентной формуле с переходом от задачи N к задаче N - 1.
 */
void recFormula(unsigned *sc, unsigned *uc, unsigned n) {
    if (n == 0) {
        // === Количество шагов для получения результата ===
        funcRecurrentTotalCount++;
        // =================================================
 
        sc[n] = 0;
        uc[n] = 1;
    }
    else {
        recFormula(sc, uc, n - 1);
 
        sc[n] = 0;
        for (unsigned i = 1; i <= n; i++) {
            // === Количество шагов для получения результата ===
            funcRecurrentTotalCount++;
            // =================================================
 
            sc[n] += C(n, i) * uc[n - i];
        }
 
        uc[n] = factorial(n) - sc[n];
    }
}
 
int main() {
    unsigned n;
    cin >> n;
    bool *select = new bool[n];
 
    for (unsigned i = 0; i < n; i++) {
        select[i] = false;
    }
 
    cout << "n! - unsuitable = " << factorial(n) - getUnsuitableCount(select, n) << endl;
    cout << "suitable = " << getSuitableCount(select, n) << endl;
 
    unsigned *sc = new unsigned[n + 1];
    unsigned *uc = new unsigned[n + 1];
 
    recFormula(sc, uc, n);
    cout << "F(n) = " << sc[n] << endl;
 
    cout << "--------------------" << endl;
    cout << "Unsuitable Total Count: " << funcUnsuitableTotalCount << endl;
    cout << "Suitable Total Count: " << funcSuitableTotalCount << endl;
    cout << "Recurrent Total Count: " << funcRecurrentTotalCount << endl;
 
    return 0;
}


Прошу прощения за мой английский, если в названиях переменных и функций есть ошибки.

1
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
18.12.2018, 16:25 11
Я пока недалеко продвинулся (если бы ещё на работе не отвлекали ) Единственное, пока заметил закономерность, то что кол-во вариантов для каждого числа на первой позиции одинаково
т.е. формула такая: (n-1)! + (n-1) * k
где k -это кол-во вариантов для одного числа на первой позиции.
при n = 3, k = 1
при n = 4, k = 3
при n = 5, k = 13
при n = 6, k = 67
осталось понять, как находить k
0
0 / 0 / 0
Регистрация: 05.10.2023
Сообщений: 1
05.10.2023, 20:40 12
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <algorithm>
using namespace std;
bool perestanovka(int* urna, int n) 
{
    for (int i = 0; i < n; ++i)
    {
        if (urna[i] == i)
        {
            return true;
        }
    }
    return false;
}
 
int main() 
{
    int ans = 0,n=10, fac = 3628800;
    int urna[10] = { 0,1,2,3,4,5,6,7,8,9 };
    for (int i = 0; i < fac; ++i) 
    {
        next_permutation(urna, urna + n);
        if (perestanovka(urna,n))
            ans++;
    }
    cout << ans << endl;
 
    return 0;
}
изичное решение, вроде также правильно
0
1709 / 1109 / 337
Регистрация: 25.01.2019
Сообщений: 2,910
06.10.2023, 00:12 13
А у меня красивая пирамидка!
Миниатюры
Подсчитать количество ситуаций, когда номер хотя бы одного вынутого шарика совпадает с порядковым номером действия  
0
1709 / 1109 / 337
Регистрация: 25.01.2019
Сообщений: 2,910
06.10.2023, 00:15 14
Кликните здесь для просмотра всего текста
ой, некропостинг
0
06.10.2023, 00:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.10.2023, 00:15
Помогаю со студенческими работами здесь

Для динамического массива подсчитать количество его отрицательных элементов с четным порядковым номером
Для динамического массива подсчитать количество его отрицательных элементов с четным порядковым...

Для динамического массива подсчитать количество его четных элементов с нечетным порядковым номером
Для динамического массива подсчитать количество его четных элементов с нечетным порядковым номером.

Для динамического массива подсчитать количество его нулевых элементов с нечетным порядковым номером
Для динамического массива подсчитать количество его нулевых элементов с нечетным порядковым...

Для динамического массива подсчитать количество его четных элементов с нечетным порядковым номером
Для динамического массива подсчитать количество его четных элементов с нечетным порядковым номером

Какое количество информации будет содержать зрительное сообщение о цвете вынутого шарика
задача Для начала, перепишите задание руками на форум в новом сообщении. Правила, п. 5.18

Найти вероятность того, что хотя бы у одного билета порядковый номер совпадет с его собственным номером
Проверьте пожалуйста решение Из ящика, содержащего n билетов с номерами: 1,2...n извлекают по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru