Codeforces Gym 101522E Expected Score【模拟】

题目来源:https://codeforces.com/gym/101522/problem/E
在这里插入图片描述
在这里插入图片描述
★这题就是一道模拟,难度不大,但是我题目看不懂,很难受awa~


翻译:

有2*n个盒子,标号为1到n,每个标号标记盒子2次。盒子的标号是不可见的(除非操作的时候取出),现在有r轮操作,每次从2n个箱子里任意取2个盒子,如果盒子标号相同,那么这轮得分即为标号;否则为0 。已经进行了r-1次操作,现在想让这最后一次操作的得分最大,求这个最大的期望


思路:

可以分4种情况讨论:
①:保守的情况,在这r-1次操作中的最大得分 可能就是最大期望,记为tmp
②:如果想比保守的情况大,那当然在 tmp+1 到n里面找,如果这里面已经有出现过两次的标记,那肯定是比①大的
③:然后就是只出现过一次的标记,(也是在tmp+1到n里面找,下面也一样,原因不用说吧 ),cnt为没有开过的箱子的数目,那匹配成功的概率是 1.0/cnt (表格里面的 i 不严谨,大家心里明白就好

tmp i
1-(1.0/cnt) 1.0/cnt

④:如果有很大的数一次都没出现,那么只能 摸鱼 了,高中数学中排列组合: 概率= 2.0/(cnt*(cnt-1)

tmp i i+1
1-tot 2.0/(cnt*(cnt-1) 2.0/(cnt*(cnt-1)
有些变量不清楚意思的话 详见代码~

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int maxn=2e5+5;
const int sz=1<<6;
const int mod=1e9+7;
const int inf=2e9+7;
typedef long long LL;
int n,m;
int num[maxn];
bool vis[maxn];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        memset(num,0,sizeof num);
        memset(vis,0,sizeof vis);
        LL cnt=2*n;
        int tmp=0;
        while(--m){
            int p1,p2,n1,n2;
            scanf("%d%d%d%d",&p1,&p2,&n1,&n2);
            if(!vis[p1]){
                vis[p1]=1;
                num[n1]++;
                cnt--;
            }
            if(!vis[p2]){
                vis[p2]=1;
                num[n2]++;
                cnt--;
            }
            if(n1==n2) tmp=max(tmp,n1);
        }
        double ans=0,sum=0,tt=cnt*(cnt-1)*1.0/2,tot=0;
        for(int i=tmp+1;i<=n;i++){
            if(num[i]==2){
                ans=max(tmp,i);
            }
        }
        for(int i=tmp+1;i<=n;i++){
            if(num[i]==1){
                 ans=max(ans,i*1.0/cnt+tmp*1.0*(1-1.0/cnt));
            }
        }
        for(int i=tmp+1;i<=n;i++){
            if(num[i]==0&&i!=tmp){
                tot+=1.0/tt;
                sum+=i*1.0/tt;
            }
        }
        sum+=(1-tot)*tmp;
       printf("%.6lf\n",max(ans,sum));
    }
    return 0;
}

发布了71 篇原创文章 · 获赞 89 · 访问量 8564

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/98740723