412. Пи
Задано произвольное множество целых чисел. Вероятность того, что выбранная наугад пара чисел из
этого множества не имеет общего делителя, равна 6 / p2. По заданному множеству найти приближенное значение
константы p.
Вход. Первая строка каждого теста содержит количество чисел
n во множестве. Далее следуют n целых чисел, каждое из которых
находится в промежутке от 0 до 32768. Последний тест содержит n = 0 и не
обрабатывается.
Выход. По
входным данным вычислить приблизительно значение p и вывести его с 6 знаками после запятой. Если p оценить не
возможно (не существует ни одной взаимно простой пары в исходном множестве), то
вывести сообщение ‘No estimate for this data set.’.
5
2
3
4
5
6
2
13
39
0
3.162278
No estimate for this data set.
полный перебор
Вероятность того, что
выбранная наугад пара чисел не имеет общего делителя, равна отношению
количества взаимно простых пар common к общему количеству пар pairs.
То есть common / pairs = 6 / p2. Откуда . Остается перебрать все пары чисел, вычислить их наибольший
общий делитель и подсчитать значения common и pairs.
В первом тесте входное множество состоит из чисел 2,
3, 4, 5, 6. Из этих пяти чисел можно составить 10 всевозможных пар: (2, 3), (2,
4), …, (5, 6). Шесть из десяти пар не имеют общих делителей: (2, 3), (2, 5),
(3, 4), (3, 5), (4, 5), (5, 6). Откуда = 3.162278.
Функция вычисления
наибольшего общего делителя gcd имеет вид:
int gcd(int
i, int j)
{
return (i) ? gcd(j % i, i): j;
}
Читаем количество чисел n во входном множестве.
Само множество заносим в массив m.
while(scanf("%d",&n),
n)
{
for(i = 0; i
< n; i++) scanf("%d",&m[i]);
Перебираем все
возможные пары чисел множества (m[i], m[j]), 0 £ i < n
– 1, i + 1 £ j < n. В переменной pairs
подсчитываем общее число таких пар, в переменной common – число взаимно
простых пар.
pairs = common = 0;
for(i = 0; i < n - 1; i++)
for(j = i + 1; j < n; j++)
{
pairs++;
if (gcd(m[i],m[j]) == 1) common++;
}
Если не существует ни одной взаимно простой пары (common
= 0), то выводим сообщение о невозможности оценить p. Иначе значение p вычисляем по выше
приведенной формуле и выводим с 6 знаками после запятой. Чтобы при делении
избежать потери точности следует один из множителей числителя (например pairs)
перевести в тип double.
if (!common) {printf("No
estimate for this data set.\n"); continue;}
res = sqrt(6*(double)pairs/common);
printf("%.6lf\n",res);
}