ARC#139 D Priority Queue 2

考虑期望上的经典套路:
\(E = \sum p_{i \leq x}\) 其中 \(p\) 为概率

把他变换到求和上:

\(S = \sum f_{i \leq x}\) 其中 \(f\) 为方案数/数量。

那么我们只要枚举 \(x\) ,考虑所有最终的序列中大于等于 \(x\) 的数量即可。

那么改为下列问题:
给定一个初始数 \(K\),每次有 \(m - x + 1\) 种方案对其 \(+1\),\(x - 1\)种方案不变,如果 \(K\) 变换完后 \(>X\) ,则对其减一,求最终 \(K\) 的权值和。

那么考虑枚举中间加的次数,最终结果和方案数容易算出。

点击查看代码
//晦暗的宇宙,我们找不到光,看不见尽头,但我们永远都不会被黑色打倒。——Quinn葵因
#include<bits/stdc++.h>
#define ll long long
#define N 2005

int n,m,k,X,a[N];

ll ans;

#define mod 998244353

ll s[N],inv[N];

inline ll qpow(ll a,ll b){
	ll res = 1;
	while(b){
		if(b & 1)res = res * a % mod;
		a = a * a % mod;b >>= 1;
	}
	return res;
}

inline int C(int x,int y){return s[x] * inv[y] % mod * inv[x - y] % mod;}

int main(){
	scanf("%d%d%d%d",&n,&m,&k,&X);
	X = n + 1 - X + 1;
	for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
	s[0] = 1;for(int i = 1;i <= k;++i)s[i] = s[i - 1] * i % mod;
	inv[k] = qpow(s[k],mod - 2);for(int i = k - 1;i >= 0;--i)inv[i] = (inv[i + 1] * (i + 1)) % mod;
	for(int i = 1;i <= m;++i){
		int si = 0;for(int j = 1;j <= n;++j)si += (a[j] >= i);
		for(int j = 0;j <= k;++j){
			ll x = qpow(m - i + 1,j) * qpow(i - 1,k - j) % mod * C(k,j) % mod,times = si + j - std::max(0,std::min(k,si + j - X + 1));
			ans = (ans + x * times) % mod;
		}
	}
	std::cout<<ans<<"\n";
} 
posted @ 2022-04-25 10:13  fhq_treap  阅读(103)  评论(1编辑  收藏  举报