题意简述
Bessie要找 头奶牛约会,第 头奶牛同意的概率是 。Bessie 会对一个连续区间的所有奶牛邀请约会,但是她只希望恰好一个同意来约会。请求出所有区间中,恰好只有一个奶牛同意约会的概率的最大值。输出这个最大的概率乘以 后下取整的结果。
,。
思路框架
设 ,。
一段区间 中只有恰好一个奶牛同意邀请的概率为: 设 ,那么这个概率为
(设 )
证明一下单调性,就珂以 做了。
具体思路
我们考虑从 变成 会怎么样。
的答案是 。
而 变成 的时候, 新乘了一个 , 新加了一个 。答案变成:
假设这个答案比 的答案优,那么
简单移项发现:
那么对于每个 ,我们找到一个最大的 满足 ,那么 就是以 为左端点的最优解了。而随着 的增大, 值显然会减小,那么 就会不断往右移(或者不变)。这就是单调性,利用这单调性,珂以轻松的 求解。
代码
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 1666666
#define real double
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define iter(a,p) (a.begin()+p)
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Rd(int cnt,...)
{
va_list args;
va_start(args,cnt);
F(i,1,cnt)
{
int* x=va_arg(args,int*);R1(*x);
}
va_end(args);
}
int n;
real p[N];
void Input()
{
R1(n);
F(i,1,n) {scanf("%lf",&p[i]); p[i]/=1e6;}
}
real a[N],b[N];
void Soviet()
{
F(i,1,n) a[i]=1.0-p[i],b[i]=p[i]/(1.0-p[i]);
//计算出a,b
int p=0;
//p维护满足条件的最大的r值
real A=1.0,B=0.0;
//一定注意!A的初始值为1!
real ans=0.0;
F(i,1,n)
{
while(p<n and B<1.0) ++p,A*=a[p],B+=b[p];
//此时p是最大的满足B<1的值+1
ans=max(ans,A*B);
//那么A*B就是以i为左端点的最优解了
A/=a[i]; B-=b[i];
}
printf("%d\n",(int)(ans*1e6));
}
#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}