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";
}