链接
https://codeforces.com/problemset/problem/1156/F
题解
排个序然后把相同的合并下,
a
i
a_i
ai表示大小为
i
i
i的数有多少个
f
i
j
f_{ij}
fij表示前
i
i
i种数,选出
j
j
j个严格递增的,概率是多少
f
i
j
=
f
i
−
1
,
j
+
f
i
−
1
,
j
−
1
a
i
n
−
j
+
1
f_{ij}=f_{i-1,j}+f_{i-1,j-1}\frac{a_i}{n-j+1}
fij=fi−1,j+fi−1,j−1n−j+1ai
统计答案就枚举最后两个是谁然后求一下和就好了
题外话
这种概率
d
p
dp
dp裸题放在
F
F
F真的没问题??
这题比
B
、
C
B、C
B、C简单多了好嘛qwq
B
B
B题硬是自闭到最后
什么玩意,出题人有毒吧qwq
代码
#include <bits/stdc++.h>
#define maxn 5050
#define mod 998244353ll
using namespace std;
typedef long long ll;
ll f[maxn][maxn], N, a[maxn], inv[maxn], s[maxn], tmp[maxn];
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void init()
{
ll i;
inv[1]=1;
for(i=2;i<maxn;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;
N=read();
for(i=1;i<=N;i++)tmp[read()]++;
auto x(0);
for(i=1;i<=N;i++)if(tmp[i])a[++x]=tmp[i];
N=x;
for(i=1;i<=N;i++)s[i]=s[i-1]+a[i];
}
void dp()
{
ll i, j;
for(i=0;i<maxn;i++)f[i][0]=1;
for(i=1;i<=N;i++)
{
for(j=1;j<=i;j++)
{
f[i][j]=f[i-1][j] + f[i-1][j-1]*a[i]%mod*inv[s[N]-j+1];
f[i][j]%=mod;
}
}
}
int main()
{
init();
dp();
ll i, j, ans(0);
for(i=1;i<=N;i++)for(j=0;j<=i-1;j++)
{
ans+=f[i-1][j] * (a[i]*(a[i]-1)%mod) %mod * (inv[s[N]-j]*inv[s[N]-j-1]%mod);
ans%=mod;
}
printf("%lld",ans);
return 0;
}