【题解】CF442B Andrey and Problem 以及 [USACO19FEB]Cow Dating P

先来看第二题。

[USACO19FEB]Cow Dating P

这是一个关于概率的问题,即求一个最优区间满足恰好有一个成立的概率最大。

我们考虑从 n 到 n+1 有什么变化(这是解决这类问题的基本思路)

∏ i = 1 n ( 1 − p i ) = x \prod_{i=1}^n (1-p_i) = x i=1n(1pi)=x

记前 n n n 项只有一个人答对的概率为 f n f_n fn

现在我们可以开始推式子。

  1. 如果第 n + 1 n+1 n+1 道题答对了, p n + 1 ∗ x p_{n+1} * x pn+1x
  2. 如果第 n + 1 n+1 n+1 道题没有答对, ( 1 − p n + 1 ) ∗ f n (1-p_{n+1})*f_n (1pn+1)fn

所以 f n + 1 = p n + 1 ∗ x + ( 1 − p n + 1 ) ∗ f n f_{n+1}=p_{n+1} * x+(1-p_{n+1})*f_n fn+1=pn+1x+(1pn+1)fn

f n + 1 − f n > 0 f_{n+1} - f_{n} > 0 fn+1fn>0 (单纯为了方便变形或者说成研究增减性)

( x − f n ) ∗ p n + 1 > 0 (x-f_n) * p_{n+1} > 0 (xfn)pn+1>0 ,等价于 x > f n x>f_n x>fn

到这里 f n f_n fn 还是变量,我们考虑消去。

考虑 f n f_n fn 的定义,从而得到:

∏ i = 1 n ( 1 − p i ) > ∏ i = 1 n ( 1 − p i ) ∗ ∑ i = 1 n p i 1 − p i \prod_{i=1}^n (1-p_i) > \prod_{i=1}^n (1-p_i)*\sum_{i=1}^n \frac{p_i}{1-p_i} i=1n(1pi)>i=1n(1pi)i=1n1pipi

∑ i = 1 n p i 1 − p i < 1 \sum_{i=1}^n\frac{p_i}{1-p_i}<1 i=1n1pipi<1

至此,我们固定右端点,然后二分左端点即可。

注意开 long double 。

#include<bits/stdc++.h> #define db long double #define fi first #define se second #define ll long long #define inf 1e9 #define eps 1e-10 using namespace std; const int N=1e6+5; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { c=getchar(); } while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x; } int n; db p[N],sum[N],mul[N],res; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%llf",&p[i]); p[i]/=1000000; } mul[0]=1; for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+p[i]/(1-p[i]); mul[i]=mul[i-1]*(1-p[i]); } for(int i=1;i<=n;i++) { int it=upper_bound(sum+1,sum+i+1,sum[i]-1)-sum-1; res=max(res,(sum[i]-sum[it])*mul[i]/mul[it]); } printf("%lld",(ll)((res+eps)*1000000)); }

利用上一题的结论,来看第一题。

CF442B Andrey and Problem

本题和上一题的区别在于并没有钦定区间。

也就是说限制少了,难度高了。

但是我们仍然可以通过分析得出结论。

假设最优答案是一个大小为 k 的某个状态。我们不难得出对于任何子集为 k-1 的满足 ∑ i = 1 k − 1 p [ a [ i ] ] 1 − p [ a [ i ] ] < 1 \sum_{i=1}^{k-1}\frac{p[a[i]]}{1-p[a[i]]}<1 i=1k11p[a[i]]p[a[i]]<1

现在考虑把其中一个数调整到更大的 p [ i ] p[i] p[i]

根据 f n + 1 = ( x − f n ) ∗ p n + 1 + f n f_{n+1}=(x-f_n) * p_{n+1}+f_n fn+1=(xfn)pn+1+fn

又因为 x − f n > 0 x-f_n>0 xfn>0 所以 p n + 1 p_{n+1} pn+1 越大答案越优。

此时将最小的 p i p_i pi 替换成较大值,可以得到更优策略,与假设前提矛盾。这样我们就证明了它。

#include<bits/stdc++.h> #define db double using namespace std; const int Maxn=1e5+5; int n,m; db p[Maxn],q[Maxn],mx; bool cmp(db x,db y) { return x>y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf",&p[i]); if(p[i]==1) { printf("1"); return 0; } } sort(p+1,p+1+n,cmp); db tmp=1,tmp2=0; for(int i=1;i<=n;i++) { q[i]=p[i]/(1-p[i]); tmp*=(1-p[i]); tmp2+=q[i]; mx=max(mx,tmp*tmp2); } printf("%.30lf",mx); }

总结:(解决这类问题的关键)

  1. 推式子的能力
  2. 问题的转化能力,学会换角度思考

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530222.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示