ABC-295 E - Kth Number

传送门

题目:

有一个长度为n的序列,由 0 和m之间的整数组成,

可以按顺序执行以下操作1和2。

  1. 对于每个等于0的元素 ,分别在1 和 m之间随机选择一个整数,并替换为该元素。

  1. 按升序排序。

思路:

qwq没思路,看的官方题解

利用这一转换,分类讨论。

利用期望的线性性,叠加讨论 1 到m的情况。

  1. 如果对于 ,若在序列中存在 n - k + 1 及以上个大于等于 i 的元素。那么该情况对答案的贡献为1。因为不管其他可变项如何取值,都无法改变第k个元素大于等于i的事实。如果存在大于等于k个元素小于i ,那么这种情况对答案的贡献为0。因为无论其他可变项如何取值都不能使得第k个元素大于等于i

  1. 除上面两种情况,剩下的就是将可变项的一部分,取值为大于等于0的值,从而使得在排序之后第k个元素的值要大于等于i。令可变项的个数为 cnt0,大于等于i的个数为cnt1,小于i的个数为cnt。从cnt0中选取j个元素。

#include <bits/stdc++.h>
#define oo 0x3f3f3f3f
#define ll long long
#define OO 0x3f3f3f3f3f3f3f3f
#define IO ios::sync_with_stdio(false);cin.tie(nullptr)
#define endl "\n"
#define int ll
const int N = 2e3 + 10, M = 2 * N;
using namespace std;
typedef pair<int, int> pii;
#define deb(i,x) if(int i==x) int k = 1; 
#define all(x) x.begin(),x.end()
ll lowbit(ll x) { return x & -x; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll qmi(ll a, ll b, ll mod)
{
    ll res = 1;
    while(b)
    {
        if(b & 1) res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res % mod;
}
const int mod = 998244353;

int c[N][N]={0};
int n, m, k;
void init(){
    for(int i = 0;i < N;i ++)
        for(int j = 0;j <= i;j ++)
            if(!j)c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
signed main(){ 
    IO;
    cin >> n >> m >> k;
    init();

    vector<int> a(n + 1);
    int cnt0 = 0;
    for(int i= 1;i <= n;i ++)
    {
        cin >> a[i];
        if(!a[i])cnt0 ++;
    }

    int ans = 0;
    //cout << "---" << endl << cnt0 << endl;
    for(int i = 1;i <= m; i++)
    {
        int cnt1 = 0;//小于 i
        for(int j = 1;j <= n;j ++)
            if(!a[j]) continue;
            else if(a[j] >= i)cnt1 ++;

        int cnt = n - cnt0 - cnt1;// 大于等于 i
        //cout << "cnt1 : " << cnt1 << endl;
        if(cnt1 > n - k + 1 || cnt >= k)
        {
            ans = (ans + (cnt1 >= n - k + 1)) % mod;
            continue;
        }

        int p = (m + 1 - i) * qmi(m, mod - 2, mod) % mod;
        int tem = ((1 - p) % mod + mod) % mod;
        for(int j = n - k + 1 - cnt1;j <= cnt0;j ++)
        {
            int lri = qmi(tem, cnt0 - j, mod);
            int lei = qmi(p, j, mod);
            int res = c[cnt0][j] % mod * lri % mod * lei % mod;
            ans = (ans + res) % mod;
        }
    }
    cout << ans << endl;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值