codeforces1156F. Card Bag

博客给出Codeforces 1156F题的链接,介绍题解思路,先排序合并相同数,用ai表示大小为i的数的数量,fij表示前i种数选出j个严格递增的概率,通过公式fij=fi−1,j+fi−1,j−1n−j+1ai计算,最后枚举最后两个数求和统计答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接

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=fi1,j+fi1,j1nj+1ai
统计答案就枚举最后两个是谁然后求一下和就好了

题外话

这种概率 d p dp dp裸题放在 F F F真的没问题??
这题比 B 、 C B、C BC简单多了好嘛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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值