正题
题目链接:https://ac.nowcoder.com/acm/contest/7329/D
题目大意
n n n个数的序列,排序后让随机 k k k个数加上 d d d,求依旧满足单调上升的期望概率
解题思路
对于一个位置加上 d d d后会让到后面一段范围内都得加上 d d d。我们预处理一个 l i l_i li表示如果 i i i加上 d d d后 [ i + 1 , l i ] [i+1,l_i] [i+1,li]都得加上 d d d。
然后设 f i , j f_{i,j} fi,j表示到第 i i i个加了 k k k次依旧满足条件的方案数。
然后 O ( n 2 ) d p O(n^2)dp O(n2)dp即可
c o d e code code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5100,XJQ=998244353;
int n,d,l[N],a[N],f[N][N],c[N][N];
int power(int x,int b){
int ans=1;
while(b){
if(b&1)ans=(ll)ans*x%XJQ;
x=(ll)x*x%XJQ;b>>=1;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
for(int i=n;i>=1;i--){
int z;l[i]=i;
for(z=i;z<=n&&a[i]+d>=a[z];z++);
z--;l[i]=l[z];
}
f[1][0]=c[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<n;j++){
int w=l[i]-i+1;
(f[l[i]+1][j+w]+=f[i][j])%=XJQ;
(f[i+1][j]+=f[i][j])%=XJQ;
}
}
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n+1;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%XJQ;
for(int i=1;i<=n;i++)
printf("%d\n",(ll)f[n+1][i]*power(c[n+1][i+1],XJQ-2)%XJQ);
}