Wannafly挑战赛3-A-珂学送分(概率dp)

题目描述

给你一个长 n 的序列,m 次查询

每次查询给一个 x,然后:

从序列的最左端 1 开始,每次随机的选择一个右端点 r,如果两个端点间的区间和不超过 x ,就进行一次分割,然后把左端点变成 r + 1, 否则一直随机下去。

问这样分割出来的期望段数

输入描述:

第一行两个数 n,m
之后一行 n 个数表示这个序列
之后m行每行一个数 x,表示求每段的和不大于 x 的情况下切割的期望段数

输出描述:

m 行,每行一个保留到小数点后2位的数表示答案
如果无论如何都没有合法的切割方案,输出"YNOI is good OI!",不含引号
示例1


题解:
 
#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 1000005
int a[maxn],sum[maxn];
double dp[maxn],sm[maxn];
int main(void)
{
	int n,m,x,mx=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum[i]=sum[i-1]+a[i];
		mx=max(mx,a[i]);
	}
	while(m--)
	{
		scanf("%d",&x);
		if(mx>x)
		{
			printf("YNOI is good OI!\n");
			continue;
		}
		dp[n]=1;sm[n]=1;sm[n+1]=0;
		for(int j=n,i=n-1;i>0;i--)
		{
			while(sum[j]-sum[i-1]>x)
				j--;
			dp[i]=1.0/(j-i+1)*(sm[i+1]-sm[j+2])+1.0;
			sm[i]=sm[i+1]+dp[i];
		}
		printf("%.2f\n",dp[1]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值