码迷,mamicode.com
首页 > 其他好文 > 详细

E. Kleofá? and the n-thlon

时间:2019-12-08 17:14:20      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:inline   res   nsis   const   any   data-   判断   probable   cond   

题目链接:http://codeforces.com/problemset/problem/602/E

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 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.

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 技术图片.

Examples
input
Copy
4 10
2
1
2
1
output
Copy
1.0000000000000000
input
Copy
5 5
1
2
3
4
5
output
Copy
2.7500000000000000
input
Copy
3 6
2
4
2
output
Copy
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.

 题目大意:大概是说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\n");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\n",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\n");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\n",ans*(M-1)+1);
    return 0;
}

 

E. Kleof&#225;? and the n-thlon

标签:inline   res   nsis   const   any   data-   判断   probable   cond   

原文地址:https://www.cnblogs.com/caijiaming/p/12006086.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!