Card Bag (Codeforces 1156F)
Tags: Math, probabilities

You have a bag which contains $$$n$$$ cards. There is a number written on each card; the number on $$$i$$$-th card is $$$a_i$$$.You are playing the following game. During each turn, you choose and remove a random card from the bag (all cards that are still left inside the bag are chosen equiprobably). Nothing else happens during the first turn — but during the next turns, after removing a card (let the number on it be $$$x$$$), you compare it with the card that was removed during the previous turn (let the number on it be $$$y$$$). Possible outcomes are:   if $$$x < y$$$, the game ends and you lose;  if $$$x = y$$$, the game ends and you win;  if $$$x > y$$$, the game continues. If there are no cards left in the bag, you lose. Cards are not returned into the bag after you remove them.You have to calculate the probability of winning in this game. It can be shown that it is in the form of $$$\frac{P}{Q}$$$ where $$$P$$$ and $$$Q$$$ are non-negative integers and $$$Q \neq 0$$$, $$$P \le Q$$$. Output the value of $$$P \cdot Q^{−1} ~(mod ~~ 998244353)$$$.

Input: The first line contains one integer $$$n$$$ ($$$2 \le n \le 5000$$$) — the number of cards in the bag.The second live contains $$$n$$$ integers $$$a_1, a_2, \dots a_n$$$ ($$$1 \le a_i \le n$$$) — the $$$i$$$-th integer is the number written on the $$$i$$$-th card. 

Output: Print one integer — the probability of winning in this game modulo $$$998244353$$$.

Note: In the first test case the probability of winning is $$$\frac{1}{10}$$$.In the second test case the probability of winning is $$$1$$$.In the third test case the probability of winning is $$$0$$$.In the fourth test case the probability of winning is $$$\frac{1}{4}$$$.

Sample Inputs:
5
1 1 4 2 3

2
2 2

5
4 5 1 3 2

4
1 3 4 3

Sample Outputs:
299473306

1

0

748683265

Solution (Python):
import sys
input = sys.stdin.readline
l = 5005
mod = 998244353
fact = [1] * (l + 1)
for i in range(1, l + 1):
    fact[i] = i * fact[i - 1] % mod
inv = [1] * (l + 1)
inv[l] = pow(fact[l], mod - 2, mod)
for i in range(l - 1, -1, -1):
    inv[i] = (i + 1) * inv[i + 1] % mod

def comb(n, r):
    return fact[n] * inv[r] * inv[n - r] % mod if n >= r >= 0 else 0
n = int(input())
a = list(map(int, input().split()))
cnt = [0] * 5005
for i in a:
    cnt[i] += 1
x = []
for i in cnt:
    if i:
        x.append(i)
dp = [0] * (n + 5)
dp[0] = 1
ans = 0
m = len(x)
for i in range(m):
    xi = x[i]
    c = xi * (xi - 1)
    for j in range(i + 1):
        ans += c * dp[j] % mod * fact[n - (2 + j)] % mod
        ans %= mod
    for j in range(i, -1, -1):
        dp[j + 1] += xi * dp[j] % mod
        dp[j + 1] %= mod
ans *= inv[n]
ans %= mod
print(ans)

Solution (Python):
p = 998244353

def process(A):
    n = len(A)
    sizes = [0 for i in range(n + 1)]
    for i in range(n):
        ai = A[i]
        sizes[ai] += 1
    d = [0, 0, 0]
    for i in range(n, -1, -1):
        m = sizes[i]
        if m != 0:
            d.append(0)
            for i in range(len(d) - 2, -1, -1):
                d[i + 1] = (d[i + 1] + m * d[i]) % p
            d[2] = (d[2] + m * (m - 1)) % p
    answer = 0
    denom = n * (n - 1)
    denom = pow(denom, p - 2, p)
    for i in range(2, len(d)):
        num = d[i]
        answer = (answer + num * denom) % p
        denom = denom * pow(n - i, p - 2, p)
    print(answer)
n = int(input())
A = [int(x) for x in input().split()]
process(A)

Solution (Python):
MOD = 998244353
MX = 10 ** 5
fact = [1]
for i in range(1, MX):
    fact.append(i * fact[-1] % MOD)
invfact = [pow(fact[-1], MOD - 2, MOD)]
for i in range(MX - 1, 0, -1):
    invfact.append(invfact[-1] * i % MOD)
invfact.reverse()

def perm(a, b):
    return fact[a] * invfact[b] % MOD
n = int(input())
from collections import Counter
ways = [1] + [0] * n
out = 0
ct = Counter(map(int, input().split()))
for i in sorted(ct):
    u = ct[i]
    u2 = u * u - u
    for i in range(n):
        out += u2 * (fact[n - i - 2] * ways[i]) % MOD
        out %= MOD
    for i in range(n - 2, -1, -1):
        ways[i + 1] += ways[i] * u
        ways[i + 1] %= MOD
print(out * invfact[n] % MOD)