CF513C Second price auction 题解

· · 题解

upd on 2025.11.14 根据要求删除部分“喵”语气词。

题解区怎么只有一篇题解喵。既然这样,本喵也来水一篇!

本喵对数据范围特别敏感,敏锐地发现 n 只有 5!小到离谱对吧。就连 L_iR_i 也只有 10^4 喵。

既然数据范围这么小,不妨大胆一点。上来就枚举这个最终出价!但是这样不好做喵。

所以稍微修一下定义:并非最终出价恰好为 x,而是最终出价不低于 x

求出来一系列数存进 s 数组后,照样还是可以算出最终出价恰好为 x 的概率!s_{x+1} - s_x 就好了。

所以最终答案的计算方式就定下来了喵!

但是这个 s 究竟该怎么求?

别急,咱们还没请出终极嘉宾——概率 DP!

反正 n 小,随便乱搞。定义 dp_{i,j} 表示前 i 个人出了价,其中有 j 个人的出价不低于我们当前枚举的价格 x

接下来就是转移了喵。

为了进行转移,我们需要知道第 i 个人的出价不低于 x 的概率。该怎么算?很显然的,就是 \dfrac { R_i - \max( L_i , x ) + 1 } { R_i - L_i + 1 } 。究其根源,不过是简单计算了一下在 [L_i,R_i] 这个区间中有多少个数不低于 x 。但是要注意,当 x 很大的时候,R_i-\max(L_i,x)+1 可能变成负数,记得和 0 取一下 \max 再进行计算。

P 为上面那个东西喵。

那么转移就显而易见了,枚举每个 j0i,转移式就是 dp_{i,j} = dp_{i-1,j} \times P + dp_{i-1,j} \times (1 - P) ,非常显然喵。

那么我们的一轮 DP 就结束了喵!

但是 s 呢?我们进行这个概率 DP 的目的是求出 s_x!对啊,所以进行完 DP 以后,咱枚举 i2n(出价高于 x 的至少要有 2 人,不然最终价就只能低于 x 了),让 s_x 加上所有 dp_{n,i} 就行了!

所以总的来说还是非常简单的,[代码](https://codeforces.com/contest/513/submission/328331491)也很短喵: ```cpp #include<bits/stdc++.h> using namespace std; const int N = 10; const int M = 1e4+5; int n,m,l[N],r[N]; long double dp[N][N],s[M],ans; int main(){ cin>>n;dp[0][0]=1.0; for(int i=1;i<=n;i++){cin>>l[i]>>r[i];m=max(m,(int)(r[i]));} for(int x=1;x<=m;x++){ for(int i=1;i<=n;i++){ long double P=1.0*max(r[i]-max(l[i],x)+1,0)/(r[i]-l[i]+1); for(int j=0;j<=i;j++)dp[i][j]=dp[i-1][j-1]*P+dp[i-1][j]*(1.0-P); } for(int i=2;i<=n;i++)s[x]+=dp[n][i]; } for(int x=1;x<=m;x++)ans+=(s[x]-s[x+1])*x; printf("%.10Lf",ans); return 0; } ``` 既然都看到这里了,给本喵留个赞好不好?求你了喵!