problem
有 nnn 个随机数生成器,第 iii 个生成器可以均匀随机地生成 [Li,Ri][L_i,R_i][Li,Ri] 内的一个实数。
现在你要玩个游戏,从第 111 个生成器到第 nnn 个生成器,每次当前生成器会生成一个数,你需要选择:
- 相信鲁迅,拿走这个数,游戏结束。
- 相信鲁迅,放弃这个数和这个生成器,使用下一个生成器(前提是下一个生成器必须存在)。
求使用使得期望答案最大的策略时,期望答案是多少。
solution
observation
:对于一个均匀随机生成 [Li,Ri][L_i,R_i][Li,Ri] 的生成器,生成数的期望为 Li+Ri2\frac{L_i+R_i}{2}2Li+Ri。
显然,如果上一个生成器产生的期望为 xxx,下一个生成器产生数的期望 yyy,且 x<yx<yx<y,肯定是选择下一个生成器。
更一般地,从后往前推。
设 fi:f_i:fi: 从第 iii 个生成器开始游戏得到的最大期望。
比较与 Li−1,Ri−1L_{i-1},R_{i-1}Li−1,Ri−1 的大小关系。
- fi>Ri−1f_{i}>R_{i-1}fi>Ri−1,则 fi−1=fif_{i-1}=f_{i}fi−1=fi
- fi<Li−1f_{i}<L_{i-1}fi<Li−1,则 fi−1=Li−1+Ri−12f_{i-1}=\frac{L_{i-1}+R_{i-1}}{2}fi−1=2Li−1+Ri−1
- otherwise\text{otherwise}otherwise,k=fi−Li−1Ri−1−Li−1⇒fi−1=k∗fi+(1−k)∗(fi+Ri−1)2k=\frac{f_{i}-L_{i-1}}{R_{i-1}-L_{i-1}}\Rightarrow f_{i-1}=k*f_{i}+(1-k)*\frac{(f_i+R_{i-1})}{2}k=Ri−1−Li−1fi−Li−1⇒fi−1=k∗fi+(1−k)∗2(fi+Ri−1)
计算方法就是加权平均。
code
#include <cstdio>
#include <iostream>
using namespace std;
#define double long double
#define maxn 1000005
#define eps 1e-7
int n;
double l[maxn], r[maxn], f[maxn];int main() {freopen( "pag.in", "r", stdin );freopen( "pag.out", "w", stdout );scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) scanf( "%Lf %Lf", &l[i], &r[i] );f[n] = ( l[n] + r[n] ) / 2;for( int i = n - 1;i;i -- ) {if( f[i + 1] - r[i] >= eps ) f[i] = f[i + 1];else if( f[i + 1] - l[i] >= eps ) {double k = ( f[i + 1] - l[i] ) / ( r[i] - l[i] );f[i] = k * f[i + 1] + ( 1 - k ) * ( r[i] + f[i + 1] ) / 2;}else f[i] = ( l[i] + r[i] ) / 2;}double ans = 0;for( int i = 1;i <= n;i ++ ) ans = max( ans, f[i] );printf( "%.5Lf\n", ans );return 0;
}