E. Kleofá? and the n-thlon
Posted caijiaming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Kleofá? and the n-thlon相关的知识,希望对你有一定的参考价值。
题目链接:http://codeforces.com/problemset/problem/602/E
Kleofáš is participating in an n-thlon - a tournament consisting of n different competitions in n different disciplines (numbered 1 through n). 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.
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 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 .
4 10
2
1
2
1
1.0000000000000000
5 5
1
2
3
4
5
2.7500000000000000
3 6
2
4
2
1.6799999999999999
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.
题目大意:大概是说m个人参加n场比赛,每场一人有一个排名,每场没有两个人排名相同,一个人最后的得分是n场比赛的排名相加,现在已知其中一个人n场比赛的排名
,求最后按照得分降序排列后,这个人的期望排名
思路:概率dp的板子题吧 ,写了两种做法 ,一种超时的,很好理解,要看的话可以先看下面这一篇超时的,思路在代码里
#include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<cstdio> #include<stack> using namespace std; typedef long long LL; #define lson rt<<1 #define rson rt<<1|1 const int maxn=1e2+5; const int maxm=1e3+5; const int INF=1e9+7; /** 分析 总共有m个人,除去本身,其它m-1个人是等性质的 所以我们只需要求出其中一个人小于等于题目中给定的分数的概率就行了 结果就是求得的概率*m-1 但是我们怎么求得某个人的总分小于等于题目中的总分的概率呢? 令dp[i][j]表示这个人第i轮得分为j的概率 所以 dp[i][j]=dp[i-1][j-k]*(1/m-1) 很好理解 这一轮你要得到分数k 概率是不是1/m-1 因为有一个分数已经确定了 */ double dp[maxn][maxm*maxn]; int a[maxn]; int main() { int N,M;scanf("%d%d",&N,&M); int sum=0; for(int i=1;i<=N;i++) { scanf("%d",&a[i]);sum+=a[i]; } if(M==1) {printf("1.000000000000000000 ");return 0;} double d=1.0/(M-1); dp[0][0]=1; for(int i=1;i<=N;i++)//N轮比赛 { for(int j=i-1;j<=i*M;j++)//第i轮最少得分也有i-1了 { //得判断此时的j是否合法 if(j>sum) break;//不可能大于总值 for(int k=1;k<=M;k++)//这一轮的得分 { if(k==a[i]) continue;//k已经被题中的人得去了 不可能再被得到 if(j<k) continue; dp[i][j]+=dp[i-1][j-k]*d;//得到这个分数的概率 } } } double ans=0; for(int i=N-1;i<sum;i++) ans+=dp[N][i]; // cout<<ans<<endl; printf("%.10lf ",ans*(M-1)+1); return 0; }
下面是利用前缀和处理了一下,去掉了一层for,所以就过了,要注意边界情况。看代码:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<cstdio> #include<stack> using namespace std; typedef long long LL; #define lson rt<<1 #define rson rt<<1|1 const int maxn=1e2+5; const int maxm=1e3+5; const int INF=1e9+7; /** 分析 总共有m个人,除去本身,其它m-1个人是等性质的 所以我们只需要求出其中一个人小于等于题目中给定的分数的概率就行了 结果就是求得的概率*m-1 但是我们怎么求得某个人的总分小于等于题目中的总分的概率呢? 令dp[i][j]表示这个人第i轮得分为j的概率 所以 dp[i][j]=dp[i-1][j-k]*(1/m-1) 很好理解 这一轮你要得到分数k 概率是不是1/m-1 因为有一个分数已经确定了 */ double dp[maxn][maxm*maxn]; int a[maxn]; double sum[maxm*maxn]; int main() { int N,M;scanf("%d%d",&N,&M); int num=0; for(int i=1;i<=N;i++) { scanf("%d",&a[i]);num+=a[i]; } if(M==1) {printf("1.000000000000000000 ");return 0;} double d=1.0/(M-1); sum[0]=dp[0][0]=1; for(int i=1;i<=N;i++)//N轮比赛 { for(int j=i;j<=i*M;j++)//第i轮最少得分也有i了 { //得判断此时的j是否合法 if(j>num) break;//不可能大于总值 int R=min(j-1,(i-1)*M);//要转移到j 上一场比赛最多能有多少分 dp[i][j]=sum[R]*d; int L=max(j-M,i-1);//要从上一轮转移过来的话 上一轮最少也有这么多 if(L) dp[i][j]-=sum[L-1]*d; if(L<=j-a[i]&&j-a[i]<=R) dp[i][j]-=dp[i-1][j-a[i]]*d; } for(int j=1;j<=i*M;j++) sum[j]=sum[j-1]+dp[i][j];//存一下前缀和 } double ans=0; for(int i=N;i<num;i++) ans+=dp[N][i]; printf("%.10lf ",ans*(M-1)+1); return 0; }
以上是关于E. Kleofá? and the n-thlon的主要内容,如果未能解决你的问题,请参考以下文章
CF601C Kleofá? and the n-thlon(期望+前缀和优化dp)
矩阵乘法&&dp加速矩阵的思路(E. Wet Shark and Blocks)
E. Mahmoud and Ehab and the xor-MST(结论&Xor)
E. Madoka and The Best University(数论&gcd)