【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望

本文主要是介绍【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

E. Kleofáš and the n-thlon
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Kleofáš is participating in an n-thlon - a tournament consisting of n different competitions in n different disciplines (numbered 1 throughn). There are m participants in the n-thlon and each of them participates in all competitions.

In each of these n competitions, the participants are given ranks from 1 to m in such a way that no two participants are given the same rank - in other words, the ranks in each competition form a permutation of numbers from 1 to m. The score of a participant in a competition is equal to his/her rank in it.

The overall score of each participant is computed as the sum of that participant's scores in all competitions.

The overall rank of each participant is equal to 1 + k, where k is the number of participants with strictly smaller overall score.

The n-thlon is over now, but the results haven't been published yet. Kleofáš still remembers his ranks in each particular competition; however, he doesn't remember anything about how well the other participants did. Therefore, Kleofáš would like to know his expected overall rank.

All competitors are equally good at each discipline, so all rankings (permutations of ranks of everyone except Kleofáš) in each competition are equiprobable.

Input

The first line of the input contains two space-separated integers n (1 ≤ n ≤ 100) and m (1 ≤ m ≤ 1000) — the number of competitions and the number of participants respectively.

Then, n lines follow. The i-th of them contains one integer xi (1 ≤ xi ≤ m) — the rank of Kleofáš in the i-th competition.

Output

Output a single real number – the expected overall rank of Kleofáš. Your answer will be considered correct if its relative or absolute error doesn't exceed 10 - 9.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Sample test(s)
input
4 10
2
1
2
1
output
1.0000000000000000
input
5 5
1
2
3
4
5
output
2.7500000000000000
input
3 6
2
4
2
output
1.6799999999999999
Note

In the first sample, Kleofáš has overall score 6. Nobody else can have overall score less than 6 (but it's possible for one other person to have overall score 6 as well), so his overall rank must be 1.


【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望   250ms

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
const int N=100+5,M=1000+5,S=1e5+5,Z=1e9+7,ms63=1061109567;
int n,m,k;
int TOP;
struct BIT
{double f[S];double query(int x){if(++x<=0)return 0;double tmp=0;for(;x;x-=x&-x)tmp+=f[x];return tmp;}void modify(int x,double v){if(++x<=0)return;for(;x<=TOP+1;x+=x&-x)f[x]+=v;}
}bit[2];
int main()
{while(~scanf("%d%d",&n,&m)){if(m==1){puts("1");return 0;}TOP=n*m;double mu=1.0/(m-1);MS(bit,0);bit[0].modify(0,1);int mysco=0;int pre=0,now=1;for(int i=1;i<=n;++i){scanf("%d",&k);mysco+=k;MS(bit[now].f,0);int top=i*m;for(int j=i;j<=top;++j){double rate=(bit[pre].query(j-1)-bit[pre].query(j-m-1))-(bit[pre].query(j-k)-bit[pre].query(j-k-1));bit[now].modify(j,rate*mu);}pre^=1;now^=1;}double ans=bit[pre].query(mysco-1);ans=ans*(m-1)+1;printf("%.12f\n",ans);}return 0;
}
/*
【trick&&吐槽】
1,这道题看似很难,然而只要沉下心来思考,发现问题细细化简后,还是完全可思考的。
2,复杂度看似很高,然而就是可以这样暴力过掉,真是暴力出奇迹的有效印证啊!
3,所以说敢想敢试是ACMer的基本素养>_<~~4,CF多组数据一定要确保完全读入才能用continue。否则是坑自己多次输出,还不如用return 0 TwT
5,树状数组的下标要从1开始不要忘记了。
6,DP的边界处理,再树状数组内部特判一下,写起来就很方便啦。【题意】
这题比较奇怪。题意是说——
有m(1000)个人,他们一同参加了n(100)场比赛。
对于每场比赛,m个人的排名都构成[1,m]的全排列。排名第i的人会得到分数i。
我们知道自己在每场比赛中的名次(设第i场的名次为a[i]),自然,也就知道了自己在每场比赛中的得分。
现在我们想要求,我们最终的比赛名次的期望。最终的比赛名次是指,如果最终时刻有k个人的分数严格比我们小,那么我们的名次便是k+1。现在求得就是这个值的期望。【类型】
期望DP【分析】
设计到期望的题目,并不一定就难得不可做。
我们发现,一共有m个人。除了我们自己之外,还有m-1个人。这m-1个人,每个人的期望得分的状况其实都是相同的。
更加具体而言,我们还有——每个人的可能得分都必然是整数。整数的范围是[n*1,n*m].
如果我们暴力一点,求得每个人对于每个得分x的概率p[x],我们自己的得分是u的话,那答案就是p[1,u)*(m-1)+1
这个显然成立,因为:一个人比我们分数低的概率*人数=比我们分数低的人数的期望,+1后就是我们名次的期望。于是问题就只剩下——p[x]怎么求?
n和m并不大,甚至说,我们感觉到人数n * 分数的上限n*m 也不过1e7。
于是,我们DP一个人的得分状况——
定义f[i][j]表示"经过了前i次考试,这个人得分为j的概率"。那么有——
f[i][j]=(f[i-1][j-1]+f[i-1][j-2]+...+f[i-1][m]-f[i-1][j-a[i]])/(m-1)这个DP的意义很简单,就是说,我们枚举这个状态,然后看看有哪些状态可以到达它。
而之前的每个可以转移状态,转移到当前状态的当步转移概率都是均等的,都是1/(m-1)。
于是,只要这一个简单的DP,就能实现题目的要求。
然而这个DP的时间复杂度却是O(n * n*m * m) 要爆炸!这里涉及到区间和,于是我们想到用树状数组优化——
把DP的时间复杂度可达O(n*n*m log(m)),然而却依然可以无压力在250ms内AC啦,啦啦啦啦!然而,树状数组还是傻叉做法。
因为这里又不涉及到动态修改,我为什么用树状数组?!
直接搞一个前缀和就好啦!【时间复杂度&&优化】
O(n*n*m log(m)) -> O(n*n*m)*/


【Codeforces Round 333 (Div 2)E】【期望DP概率做法 前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望   46ms

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
const int N=100+5,M=1000+5,S=1e5+5,Z=1e9+7,ms63=1061109567;
int n,m,k,pre,now;
double s[2][S+M];
inline double query(int x)
{return x<0?0:s[pre][x];
}
int main()
{while(~scanf("%d%d",&n,&m)){if(m==1){puts("1");return 0;}int top=n*m;double mu=1.0/(m-1);for(int i=0;i<=top;++i)s[0][i]=1;int mysco=0;pre=0;now=1;for(int i=1;i<=n;++i){scanf("%d",&k);mysco+=k;for(int j=0;j<i;++j)s[now][j]=0;for(int j=i;j<=top;++j){double rate=(query(j-1)-query(j-m-1))-(query(j-k)-query(j-k-1));s[now][j]=s[now][j-1]+rate*mu;}pre^=1;now^=1;}double ans=s[pre][mysco-1];ans=ans*(m-1)+1;printf("%.12f\n",ans);}return 0;
}
/*
【trick&&吐槽】
1,这道题看似很难,然而只要沉下心来思考,发现问题细细化简后,还是完全可思考的。
2,复杂度看似很高,然而就是可以这样暴力过掉,真是暴力出奇迹的有效印证啊!
3,所以说敢想敢试是ACMer的基本素养>_<~~4,CF多组数据一定要确保完全读入才能用continue。否则是坑自己多次输出,还不如用return 0 TwT
5,树状数组的下标要从1开始不要忘记了。
6,DP的边界处理,再树状数组内部特判一下,写起来就很方便啦。【题意】
这题比较奇怪。题意是说——
有m(1000)个人,他们一同参加了n(100)场比赛。
对于每场比赛,m个人的排名都构成[1,m]的全排列。排名第i的人会得到分数i。
我们知道自己在每场比赛中的名次(设第i场的名次为a[i]),自然,也就知道了自己在每场比赛中的得分。
现在我们想要求,我们最终的比赛名次的期望。最终的比赛名次是指,如果最终时刻有k个人的分数严格比我们小,那么我们的名次便是k+1。现在求得就是这个值的期望。【类型】
期望DP【分析】
设计到期望的题目,并不一定就难得不可做。
我们发现,一共有m个人。除了我们自己之外,还有m-1个人。这m-1个人,每个人的期望得分的状况其实都是相同的。
更加具体而言,我们还有——每个人的可能得分都必然是整数。整数的范围是[n*1,n*m].
如果我们暴力一点,求得每个人对于每个得分x的概率p[x],我们自己的得分是u的话,那答案就是p[1,u)*(m-1)+1
这个显然成立,因为:一个人比我们分数低的概率*人数=比我们分数低的人数的期望,+1后就是我们名次的期望。于是问题就只剩下——p[x]怎么求?
n和m并不大,甚至说,我们感觉到人数n * 分数的上限n*m 也不过1e7。
于是,我们DP一个人的得分状况——
定义f[i][j]表示"经过了前i次考试,这个人得分为j的概率"。那么有——
f[i][j]=(f[i-1][j-1]+f[i-1][j-2]+...+f[i-1][m]-f[i-1][j-a[i]])/(m-1)这个DP的意义很简单,就是说,我们枚举这个状态,然后看看有哪些状态可以到达它。
而之前的每个可以转移状态,转移到当前状态的当步转移概率都是均等的,都是1/(m-1)。
于是,只要这一个简单的DP,就能实现题目的要求。
然而这个DP的时间复杂度却是O(n * n*m * m) 要爆炸!这里涉及到区间和,于是我们想到用树状数组优化——
把DP的时间复杂度可达O(n*n*m log(m)),然而却依然可以无压力在250ms内AC啦,啦啦啦啦!然而,树状数组还是傻叉做法。
因为这里又不涉及到动态修改,我为什么用树状数组?!
直接搞一个前缀和s[2][S]就好啦!【时间复杂度&&优化】
O(n*n*m log(m)) -> O(n*n*m)*/


这篇关于【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/610478

相关文章

智能客服到个人助理,国内AI大模型如何改变我们的生活?

引言 随着人工智能(AI)技术的高速发展,AI大模型越来越多地出现在我们的日常生活和工作中。国内的AI大模型在过去几年里取得了显著的进展,不少独创的技术点和实际应用令人瞩目。 那么,国内的AI大模型有哪些独创的技术点?它们在实际应用中又有哪些出色表现呢?此外,普通人又该如何利用这些大模型提升工作和生活的质量和效率呢?本文将为你一一解析。 一、国内AI大模型的独创技术点 多模态学习 多

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

六西格玛培训公司:解锁成功之门,让企业与个人共赴“嗨”途

在竞争激烈的21世纪,六西格玛培训公司手握一把神奇的钥匙,帮助企业及个人轻松开启成功的大门。 对企业来说: 产品质量飞跃:不再是偶尔的精品,而是每个产品都如同精雕细琢的艺术品,吸引无数顾客争相购买。 工作流程优化:六西格玛培训如同精准的剪刀,剪去冗余,让工作流程更加顺畅高效。 客户满意度飙升:深谙客户需求的六西格玛,帮助企业精准把握市场脉搏,让每位客户都感受到宾至如归的满意。 战略转型游刃有

IOS 数组去重的几种方式

本来只知道NSSet和KeyValues的。今天又新学了几种方式 还有就是和同事学的一种方式 外层循环从0开始遍历,内层从最后一个元素开始遍历 for(int i=0;i<index;i++){  for(int j=index-1;j>i;j-- ){ } }

写一个坏越的个人天地(二)

小红书上搜了下博客,感觉好像没有让自己喜欢的。昨天刚好学了点grid布局,来试试 菜单栏直接使用el-menu 下边布局就用grid局部了,这块初步想法是轮播+你的天气和我的天气+自我介绍 天气的话,这边要先找一下有没有天气的api 我这边百度搜了个聚合的api,一天可以免费调用50次,应该是够了吧~要用代理,不然会报cors import axios from 'axios

如何在OS中获得SSD的寿命耐久度

这里还是以DELL的机器为例,通常DELL的服务器带有的磁盘会有显示SSD耐久度,当然也不排除SSD更新太快,有部分SSD无法在戴尔的服务器上查看到SSD的耐久度,但实际上本身只要是SSD肯定还是可以有方法查看SSD的耐久度,可以通过OS的方式进行查看,以RHEL7.9为例 首先我们需要下载安装DELL的PERCCLI的阵列卡工具,该工具可以很好的查看DELL服务器上的阵列卡对应的信息,如阵列卡

个人博客文章目录索引(持续更新中...)

文章目录 一、Java基础二、Java相关三、MySql基础四、Mybatis基础及源码五、MybatisPlus基础六、Spring基础及源码七、Tomcat源码八、SpringMVC基础及源码   随着文章数量多起来,每次着急翻找半天,而是新申请的域名下来了,决定整理下最近几年的文章目录索引。(红色标记为常检索文章) 一、Java基础 1、Java基础(一):语言概述2、J

Java基础(二)——数组,方法,方法重载

个人简介 👀个人主页: 前端杂货铺 ⚡开源项目: rich-vue3 (基于 Vue3 + TS + Pinia + Element Plus + Spring全家桶 + MySQL) 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步至千里,积小流成江海 🥇推荐学习:🍖开源 rich-vue3 🍍前端面试

6月21日训练 (东北林业大学)(个人题解)

前言:   这次训练是大一大二一起参加的训练,总体来说难度是有的,我和队友在比赛时间内就写出了四道题,之后陆陆续续又补了了三道题,还有一道题看了学长题解后感觉有点超出我的能力范围了,就留给以后的自己吧。话不多说,上正文。 正文:   Problem:A 幸运数字: #include <bits/stdc++.h>using namespace std;int sum,ans;in

上海邀请赛 A题目 HDU 5236(dp)

先求出没有ctrl+s的时候构造长度为i的期望f[i] 。然后枚举保存的次数,求出最小即可。 #include<cstdio>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<iostream>#include<map>