牛客练习赛69D-火柴排队【dp】

正题

题目链接: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);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值