《中山大学内部选拔(一)》 游戏
来源:互联网 发布:滨州大数据产业园 编辑:程序博客网 时间:2024/06/06 03:48
【问题描述】
A,B两人各有不同分值的 M 张牌,他们进行N回合的游戏,每个回合两人分别在自己的M张牌里抽取1张,然后记下各自的分数并把牌收回到自己的牌堆中,然后继续下一回合。游戏结束后,两人的得分就是各自每回合的分值和,如果其中一个人的分数和较大,则这个人就赢得比赛。
现在告诉你A,B两人各自M张牌的分值以及游戏的回数,请你计算A赢得比赛的概率。
【输入格式】
首先是T,表示数据组数。
每组数据包含4行:第1行为M,第2行为A的M张牌的分值,第3行是B的M张牌的分数。第4行为N。
【输出格式】
输出一个保留6位小数的实数,表示A赢得比赛的概率。
【输入样例】
1
10
5 9 6 12 13 15 52 11 11 11
8 9 6 3 2 1 85 9 2 3
15
【输出样例】
0.620092
【数据范围】
1<=M<=100 0<=N<=50 每张牌的分值不超过50。
【来源】
《中山大学内部选拔(一)》
这道题我拿到的题数据范围有误害的我好一阵乱优化,结果其实直接就能过。
很明显这是一道数学期望,我们可以直接用递推得到2个人分别得到每个分数的概率,这时我们要用一个前缀和的思想,把乙的分数的前缀和算出来,用g(i)表示乙得到小于等于i的分数的概率。然后没举每个i用甲得到分数i的概率乘上g(i-1),全部加起来就是答案了。
详细代码如下:(有点丑,毕竟乱优化了一波)
#include<cstdlib>#include<cstring>#include<cstdio>#include<iostream>#include<vector>#include<algorithm>using namespace std;typedef long long ll;const int maxn=1000005;double d[maxn],q[maxn],g[maxn],p,a1[maxn],b1[maxn];int a[maxn],b[maxn],cnt1,cnt2;int m,n;int main(){ freopen("Game.in","r",stdin); freopen("Game.out","w",stdout); int T; scanf("%d",&T); while(T--) { cnt1=cnt2=1; scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d",&a[i]); sort(a+1,a+1+m); for(int i=1;i<=m;i++) scanf("%d",&b[i]); sort(b+1,b+1+m); p=1.0/(double)m; scanf("%d",&n); memset(d,0,sizeof(d)); memset(a1,0,sizeof(a1)); memset(b1,0,sizeof(b1)); for(int i=2;i<=m;i++) { if(a[i]!=a[i-1]) a[++cnt1]=a[i]; else a1[cnt1]+=p; } for(int i=1;i<=cnt1;i++) a1[i]+=p,d[a[i]]=a1[i]; for(int i=2;i<=n;i++) for(int j=a[cnt1]*i;j>=a[1]*(i-1);j--)//算甲前i次得到j分的概率 { double ans=0; for(int k=1;k<=cnt1;k++) { if(j-a[k]<a[1]*(i-1)) break; ans+=d[j-a[k]]*a1[k]; } d[j]=ans; } memset(q,0,sizeof(q)); for(int i=2;i<=m;i++) { if(b[i]!=b[i-1]) b[++cnt2]=b[i]; else b1[cnt2]+=p; } for(int i=1;i<=cnt2;i++) b1[i]+=p,q[b[i]]=b1[i]; for(int i=2;i<=n;i++) for(int j=b[cnt2]*i;j>=b[1]*(i-1);j--)算乙前i次得到j分的概率 { double ans=0; for(int k=1;k<=cnt2;k++) { if(j-b[k]<b[1]*(i-1)) break; ans+=q[j-b[k]]*b1[k]; } q[j]=ans; } memset(g,0,sizeof(g)); int ans2=0; int t=max(b[cnt2],a[cnt1])*n; for(int i=b[1]*n;i<=t;i++)//算前缀和g,主要范围 g[i]=g[i-1]+q[i]; double ans=0; for(int i=a[1]*n;i<=t;i++)//求答案 ans+=g[i-1]*d[i]; printf("%.6lf\n",ans); } return 0;}
1 0
- 《中山大学内部选拔(一)》 游戏
- 中山大学c++视频笔记(一)
- Cpp环境【中山大学2004年集训队内部选拔赛】【CQYZOJ1595】小树
- 中山大学软件工程操作系统实验一报告
- 【选拔题】2009南海集训队初中选拔题一
- 校内选拔(六)
- EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔) 在哈尔滨的寒风中 (棋盘跳马对数)
- (substr strstr 的学习) EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔) G1. 唐纳德与子串 (Easy)
- EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔)
- EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔) 题解
- 常用内部控件(一)
- C++ 内部排序(一)
- 深入Memcached内部(一)
- JavaScript内部对象(一)
- 中山大学delphi视频下载(51讲)
- Nepire的校OJ入门题解—蓝桥选拔篇(一)
- Nepire的校OJ入门题解—17蓝桥选拔篇(一)
- 中山大学软件工程中级实训阶段一自学报告
- Spring 注解
- 射频识别技术漫谈(11)——Mifare系列卡的共性
- dragger2的入门基础
- 扫雷实用帖:HBase读延迟的12种优化套
- JS内置对象
- 《中山大学内部选拔(一)》 游戏
- nginx for windows再编译版
- 排序算法:快速排序
- Android studio gradle 下载很缓慢的解决方法
- 浅析Rxjava(一)
- Jmeter中正则表达式提取器使用详解
- bzoj3298
- Jin Ge Jin Qu hao UVA
- 关于微信公众号回复消息乱码的问题