1. 程式人生 > >Comet OJ - Contest #2 B 她的想法、他的戰鬥(概率 + 數學)

Comet OJ - Contest #2 B 她的想法、他的戰鬥(概率 + 數學)

二次 ++ air ont tchar while html gin rst

題目描述

Takuru 是一名情報強者,所以他想利用他強大的情報搜集能力來當中間商賺差價。

Takuru 的計劃是讓 Hinae 幫他去市場上買一個商品,然後再以另一個價格賣掉它。Takuru 會給 Hinae 一定的錢 p?p?。(p?p? 是一個非負的實數)

這個商品的市場價是一個在 [l, r]?[l,r]? 內均勻隨機的實數。

如果 p \geqslantp? 市場價,那麽 Hinae 會買下這個商品,然後私吞剩下的錢。也就是說,Takuru 以 pp 的代價買來了這個商品。

如果 p <p< 市場價,那麽 Hinae 既不會買下商品,又不會私吞任何錢。也就是說,Takuru 的利潤為 0?0?。

當 Hinae 買下了商品後,Takuru 會生成一個在 [L, R][L,R] 內均勻隨機的實數 qq,並把商品以 qq 的價格賣掉。那麽 Takuru 的利潤就是 q - p?qp?。

Takuru 想要獲得最多的利潤,所以你要幫 Takuru 確定給 Hiane 的錢 pp,使得 Takuru 的期望利潤最大。請求出最大的期望利潤。

輸入描述

第一行兩個正整數 ll 和 rr (1\leqslant l < r \leqslant 20001?l<r?2000)。

第二行兩個正整數 LL 和 RR (1\leqslant L < R \leqslant 20001?L<R?2000)。

輸出描述

一個實數,表示最大的期望利潤。(四舍五入後保留 44 位小數,輸出超過 44 位或少於 44位都會獲得 Wrong Answer。)

如果答案為 00,請不要輸出多余的負號。

若答案為 vv,保證 v+10^{-6}v+106 以及 max(v-10^{-6},0)max(v106,0) 四舍五入後保留 44 位小數的結果不會改變。

樣例輸入 1

400 1200
600 1800

樣例輸出 1

200.0000

樣例輸入 2

1999 2000
1 2

樣例輸出 2

0.0000


思路:
因為主人公的售價是 L~R 所以 主人公售價的期望是 (L+R)/2
我們給買手的錢是p,那麽我們主人公的利潤就是 ((L+R)/2-p)
我們知道 期望=值*概率
利潤期望=利潤值*概率

我們來看下概率,
P必須取到 l和r之間,因為如果p大於r,那麽不是最優的選擇,因為可以選擇r可以產生更好的利益。
而p小於l的話,買手會無法購物商品,所以也不可以。
那麽p就在 l和r之間了,
買手能買商品的時候當且僅當 商品的市場價 恰好小於等於p,也就是市場價y小於p時,可以購買,
那麽y的範圍時 l~p,總範圍是l~r,所以概率是 (p-l)/(r-l)
期望就是
((L+R)/2-p)*(p-l)/(r-l)
公式就是一個關於p的二次函數,並且a是小於等於0的,有極大值,我們判定對稱軸是否在l到r之間,
如果在,那麽函數的極值就是答案,如果不在,那麽取區間的左右極限的較大值是答案。
註意處理以下0*負數=-0的情況,

細節見code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), ‘\0‘, sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
double l,r;
double L,R;
int main()
{
    //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
    //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    
    gbtb;
    cin>>l>>r;
    cin>>L>>R;
    double t=(L+R)/2.00;
    double k=(r-l);
    double a=-1.00/k;
    double b=(t+l)/k;
    double c=-l*t/k;
    double x=-b/(2.00*a);
    double ans;
    if(x>=l&&x<=r)
    {
        ans=(4*a*c-b*b)/(4*a);
        // db(a*x*x+b*x+c);
    }else
    {
        ans=a*l*l+b*l+c;
        ans=max(ans,a*r*r+b*r+c);
    }
    ans+=eps;
    ans=max(0.0,ans-eps);
    cout<<fixed<<setprecision(4)<<ans<<endl;
    
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch ==   || ch == \n);
    if (ch == -) {
        *p = -(getchar() - 0);
        while ((ch = getchar()) >= 0 && ch <= 9) {
            *p = *p * 10 - ch + 0;
        }
    }
    else {
        *p = ch - 0;
        while ((ch = getchar()) >= 0 && ch <= 9) {
            *p = *p * 10 + ch - 0;
        }
    }
}



Comet OJ - Contest #2 B 她的想法、他的戰鬥(概率 + 數學)