zoukankan      html  css  js  c++  java
  • E. Kleofáš and the n-thlon

    题目链接: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
    ");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;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    m-n的随机整数 包括m n
    获取url参数 hash类型
    js 数组转带空格字符串
    产生n-m的随机数组
    js 判断android、IOS
    判断是否微信浏览器
    文本左右对齐方式css
    H5微信支付流程
    H5微信授权登录流程
    H5页面 input禁止弹出键盘
  • 原文地址:https://www.cnblogs.com/caijiaming/p/12006086.html
Copyright © 2011-2022 走看看