列表

详情


NC218913. BirthdayParadox

描述


The probability of n unique birthdays among n people.

The Birthday Paradox is the name given to the surprising fact that if there are just 23 people in a group, there is a greater than chance that a pair of them share the same birthday. The underlying assumptions for this are that all birthdays are equally likely (which isn't quite true), the year has exactly 365 days (which also isn't true), and the people in the group are uniformly randomly selected (which is a somewhat strange premise). For this problem, we'll accept these assumptions.

Consider what we might observe if we randomly select groups of P=10 people. Once we have chosen a group, we break them up into subgroups based on shared birthdays. Among many other possibilities, we might observe the following distributions of shared birthdays:
Of course, these distributions have different probabilities of occurring.

Your job is to calculate this probability for a given distribution of people sharing birthdays. That is, if there are P people in a group, how probable is the given distribution of shared birthdays (among all possible distributions for P people chosen uniformly at random)?

输入描述

The first line gives a number n where . The second line contain integers c_1 through c_n, where  for all c_i. The value c_i represents the number of people who share a certain birthday (and whose birthday is distinct from the birthdays of everyone else in the group).

输出描述

Compute the probability b of observing a group of people with the given distribution of shared birthdays. Since b may be quite small, output instead . Your submission's answer is considered correct if it has an absolute or relative error of at most  from the judge's answer.

示例1

输入:

2
1 1

输出:

-0.001191480807419

示例2

输入:

7
1 1 2 1 3 1 1

输出:

-4.310614508857128

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Python3(3.9) 解法, 执行用时: 37ms, 内存消耗: 4472K, 提交时间: 2021-03-07 17:13:45

from math import log10
JC = [0]
for i in range(1,365*101):
    JC.append(JC[-1]+log10(i))
def C(m,n):
    return JC[m]-JC[n]-JC[m-n]
n = int(input())
ls = input().split(' ')
ls = [int(i) for i in ls]
sm=sum(ls)
a=C(365,n)
b=365
hav = 0
for i in range(1,101):
    cur = ls.count(i)
    if cur != 0:
        a += C(n-hav,cur)
        hav += cur
hav = 0
for i in ls:
    a += C(sm-hav,i)
    hav += i

print(a-sm * log10(b))
# x=10**(-4.310614508857128+log10(b))//A(365,7)
# print(x)

C++(clang++11) 解法, 执行用时: 6ms, 内存消耗: 640K, 提交时间: 2021-03-07 14:18:49

#include<cstdio>
#include<cmath>
int cnt[105];
double lfrac[40000];
int main()
{
	int n,i,c,C = 0;
	double ans;
	for(i=2;i<40000;i++)lfrac[i] = lfrac[i-1]+log10(i);
	scanf("%d",&n);
	ans = lfrac[365]-lfrac[365-n];
	while(n--)
	{
		scanf("%d",&c), C += c, cnt[c]++;
		ans -= lfrac[c];
	}
	for(i=1;i<=100;i++)ans -= lfrac[cnt[i]];
	ans = ans+lfrac[C]-C*log10(365);
	printf("%.9lf",ans);
	return 0;
}

上一题