阿里笔试3.27场 第二题

看到群里有人讨论这题,觉得还不错就拿来写了。但只想出来 n 2 n^2 的做法,不知道有没有更优秀的做法。
评论区见

题意

输入n,表示n<=2000个数,然后接下来2行,第一行就是第i个数的下界 l i l_i ,一共n个数。第二行就是第i个数的上界 r i r_i ,一共n个数,然后每个数取值区间就是 [ l i , r i ] [l_i,r_i] ,区间每个数取到的概率相同。
让你求n个数中最小值的期望
样例:
input
2
1 2
3 3
output:
1.83333
解释:
最小值1:(1,2) (1,3) p = 1/3
最小值2:(2,2) (2,3) (3,2) p = 1/2
最小值3:(3,3) p = 1/6
ans = 1 * (1/3) + 2 * (1/2 ) + 3 * (1/6) = 1.83333

思路

首先想到枚举每个最小值,对于每个最小值有一定的范围,就是 l l 的min,和 r r 的min,因为如果取得最小值大于了 r r 的min,那么这个无论怎么取,最小值一定不是它。然后找到一个最小值的范围,那么怎么统计在这个为最小值的情况的概率,当最小值为x的是时候,对于有区间 l l < x的,这里面的所有组合情况就是每个区间的个数( ( r i x + 1 ) (r_i - x + 1) )的概率组合情况,但是这里算出来的包含了最小值为x+1,x+2…的答案,所以只需要把x+1,x+2依次减去就合理了。

code(只过了样例)

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
struct node{
    int l,r;
}a[man];
double res[man];

int main() {
    #ifndef ONLINE_JUDGE
	  //freopen("in.txt", "r", stdin);
	  //freopen("out.txt","w",stdout);
    #endif
    int n;
    cin >> n;
    int min_l = INT_MAX,min_r = INT_MAX;
    for(int i = 1;i <= n;i++)cin >> a[i].l,min_l = min(min_l,a[i].l);
    for(int i = 1;i <= n;i++)cin >> a[i].r,min_r = min(min_r,a[i].r);
    double ans = 1.0;
    for(int i = min_l;i <= min_r;i++){
        for(int j = 1;j <= n;j++){
            if(a[j].l<i){
                ans *= 1.0*(a[j].r - i + 1)/(a[j].r - a[j].l + 1); 
            }
        }
        res[i] = ans;
        ans = 1.0;
    }
    ans = 0.0;
    double sum = 0.0;
    for(int i = min_r;i >= min_l;i--){
        res[i] -= sum;
        sum += res[i];
        ans += res[i]*i;
    }
    printf("%.6lf\n",ans);
    return 0;
}
原创文章 93 获赞 12 访问量 9003

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/105209279
今日推荐