我们可以先去计算所有方案的总和,然后除以方案数c,即为最终的期望,其中c=C(n,2)=2n×(n−1)
我们可以考虑每一个元素对答案的贡献
对于元素x,记其在n组卡片出现的个数为k
k=1,即只有一组卡片出现过,那么对答案的贡献为n−1
k≥2,那么有两种情况
情况1:选择的两组卡片,都含有元素x
情况2:选择的两组卡片,只有一组含有元素x
我们可以先考虑选择的两组卡片,至少有一组含有元素x,对应的方案数为k×(n−1),但是上述计算会把情况1多算一次,因此还需要把情况1对答案的贡献去除,情况1对应的贡献为2k×(k−1)
O(n)
C++
#include <bits/stdc++.h> 
using namespace std;
int main() {
    unordered_map<int, int> mp;
    int n;
    cin >>n;
    for (int i=0; i<n; i++) {
        int m;
        cin>>m;
        while (m--) {
            int x;
            cin >> x;
            mp[x]++;
        }
    }
    long long sum = 0;
    for (auto p : mp) {
        int k = p.second;
        if(k==1){
            sum+=1ll*k*(n-1);
        }
        else{
            sum += k*(n-1) - k*(k-1)/2;
        }
    }
    long long c=1ll*n*(n-1)/2;
    printf ("%.7f", (double)sum /c);
}
python代码
n = int(input().strip())
mp = {}
for _ in range(n):
    w = list(map(int,input().split()))
    for i in range(1,len(w)):
        x = w[i]
        if x in mp:
            mp[x] += 1
        else:
            mp[x] = 1
sum = 0
for k in mp.values():
    if k == 1:
        sum += k * (n - 1)
    else:
        sum += k * (n - 1) - k * (k - 1) // 2
c = n * (n - 1) // 2
print("{:.7f}".format(sum / c))
Java代码
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            int m = scanner.nextInt();
            while (m-- > 0) {
                int x = scanner.nextInt();
                map.put(x, map.getOrDefault(x, 0) + 1);
            }
        }
        long sum = 0;
        for (int k : map.values()) {
            if (k == 1) {
                sum += (long) k * (n - 1);
            } else {
                sum += (long) k * (n - 1) - (long) k * (k - 1) / 2;
            }
        }
        long c = (long) n * (n - 1) / 2;
        System.out.printf("%.7f", (double) sum / c);
    }
}
        小美有很多组卡片,每个卡片上有一个值。现在他想随意取出两组卡片将他们混在一起,这时他会剔除值相同的卡片,将每个值相同的卡片只留下一张,现在他想知道他这个操作得到的新的一组卡片的个数的期望是多少。
第一行一个整数n,表示有n组卡片(2≤n≤200000)。
接下来n行,每行第一个整数m,表示这个卡组有m张卡片,接下来有m个整数ai,表示每个卡片上的值(1≤n≤109)。数据保证每个卡组中的卡片值互不相同,并且所有集合的长度之和不超过200000。
输出一个浮点数,表示新卡组的个数的期望。如果你的答案和标准答案的相对误差不超过10^-7,则认为答案正确。
输入
2
5 1 2 3 4 5
4 1 2 3 4
输出
5.00000000000
说明
只有两个卡组,则一定会取这两个数组,并集为1,2,3,4,5,则期望为5。