定义 d p [ i ] dp[i] dp[i]为 [ i , n ] 分 段 的 期 望 [i,n]分段的期望 [i,n]分段的期望
那么 d p [ n ] = 1 dp[n]=1 dp[n]=1
对 于 确 定 的 i , 设 我 们 找 到 了 最 大 的 j 满 足 ∑ k = i j a k < x 对于确定的i,设我们找到了最大的j满足\sum\limits_{k=i}^{j}a_k<x 对于确定的i,设我们找到了最大的j满足k=i∑jak<x
说 明 i 可 以 分 裂 到 [ i , j ] 上 的 任 意 一 个 点 去 , 那 么 有 j − i + 1 种 可 能 说明i可以分裂到[i,j]上的任意一个点去,那么有j-i+1种可能 说明i可以分裂到[i,j]上的任意一个点去,那么有j−i+1种可能
在 [ i , j ] 上 任 取 一 点 k 表 示 [ i , k ] 分 成 一 段 , 贡 献 期 望 是 1 j − i + 1 ∗ d p [ k + 1 ] 在[i,j]上任取一点k表示[i,k]分成一段,贡献期望是\frac{1}{j-i+1}*dp[k+1] 在[i,j]上任取一点k表示[i,k]分成一段,贡献期望是j−i+11∗dp[k+1]
又 发 现 对 于 i 来 说 , 如 果 i 递 减 , j 也 递 减 , 所 以 可 以 维 护 后 缀 和 来 解 决 又发现对于i来说,如果i递减,j也递减,所以可以维护后缀和来解决 又发现对于i来说,如果i递减,j也递减,所以可以维护后缀和来解决
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int a[maxn],pre[maxn],n,m,maxx;
double dp[maxn],su[maxn];
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
{
cin >> a[i];
pre[i]=pre[i-1]+a[i];
maxx=max( maxx,a[i] );
}
while( m-- )
{
int x; cin >> x;
if( maxx>x )
{
printf("YNOI is good OI!\n");
continue;
}
su[n]=1,su[n+1]=0;
dp[n]=1;
int j=n;
for(int i=n-1;i;i-- )
{
while( pre[j]-pre[i-1]>x ) j--;
//i位置可以转移到[i,j]
dp[i]=1.0/( j-i+1 )*( su[i+1]-su[j+2] )+1.0;
su[i]=su[i+1]+dp[i];
}
printf("%.2f\n",dp[1]);
}
}