其他分享
首页 > 其他分享> > hdu6693 Valentine's Day

hdu6693 Valentine's Day

作者:互联网

题目好难懂orz自闭

 

题意:

某人要给他女朋友买礼物,他想求他买的这些礼物让他女朋友只笑一次的概率最大是多少

但是他也没给你他要买哪些,,

题解:

贪心从最大的开始买,假设选了前k件最大的,那么答案就是

ans=\sum_{i=1}^{k}p[i]\prod _{j\neq i}^{k}(1-p[j])

想办法优化这个

一般我们的操作就是前缀和和前缀积

化简、

ans=\sum_{i=1}^{k}\frac{p[i]}{1-p[i]}\prod _{j=1}^{k}(1-p[j])

设前缀积suf[i]=\prod _{j=1}^{i}1-p[j]

上面式子化成了

ans=suf[i]*\sum_{i=1}^{k}\frac{p[i]}{1-p[i]}

这个求和明显可以用前缀和搞定

sum[k]=\sum_{i=1}^{k}\frac{p[i]}{1-p[i]}

则,化简成

ans=suf[i]*sum[i]

这样枚举i从1到n即可

但是:当p[1]=1.0的时候,1-p[1]=0这样前缀和就不对了(除零错误),所以要特判一下

 

/*author:revolIA*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
double p[maxn],sum[maxn]={1},suf[maxn];
int main(){
    int t,n;
    for(scanf("%d",&t);t--;){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
        sort(p+1,p+1+n,greater<double>());
        if(p[1] == 1){
            printf("%.12f",1.0);
            continue;
        }
        for(int i=1;i<=n;i++){
            sum[i] = sum[i-1]*(1-p[i]);
            suf[i] = suf[i-1]+p[i]/(1-p[i]);
        }
        double ans = 0;
        for(int i=1;i<=n;i++)ans = max(ans,sum[i]*suf[i]);
        printf("%.12f\n",ans);
    }
    return 0;
}

 

 

标签:化简,前缀,int,scanf,long,Valentine,hdu6693,maxn,Day
来源: https://blog.csdn.net/Du_Mingm/article/details/100009782