codeforces 602 E. Kleofáš and the n-thlon (概率dp)

题意:有 n n 个人进行了m场比赛,告诉你了自己的每场排名,并且一场比赛中不会有并列,问最后自己的期望排名
题解:很明显期望 dp d p

dp[i][j]ij d p [ i ] [ j ] 表 示 进 行 了 i 场 比 赛 得 分 为 j 的 期 望 人 数
那么转移就是 dp[i][j]=(j1k=jmdp[i][k]dp[i][ja[i]])/(m1) d p [ i ] [ j ] = ( ∑ k = j − m j − 1 d p [ i ] [ k ] − d p [ i ] [ j − a [ i ] ] ) / ( m − 1 )
对于每一个可能的状态,都有 1/(m1) 1 / ( m − 1 ) 的概率转移过来
初始化 dp[0][0]=m1 d p [ 0 ] [ 0 ] = m − 1
这里简单的维护一个前缀和就可以,然后貌似 nnm n ∗ n ∗ m 这题数组正好开的下,不过使用滚动数组更好就是了


#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <sstream>
#include <cmath>
#define LL long long
#define mod 1000000007
using namespace std;
const int maxn = 500000 + 5;
const LL INF = 1e18 + 5;
int a[maxn];
double dp[2][100*1000 + 5];
double sum[2][100*1000+5];
int main(){
    int n,m;
    int tot = 0;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++){
        scanf("%d",&a[i]);
        tot += a[i];
    }
    dp[0][0] = m-1;
    for(int j=0; j<=n*m; j++)
        sum[0][j] = m-1;
    for(int i=1; i<=n; i++){
        memset(dp[i%2], 0, sizeof(dp[i%2]));
        memset(sum[i%2], 0, sizeof(sum[i%2]));
        for(int j=i; j<=i*m; j++){
            int top = j-1;
            int bottom = max(0,j-m);
            if(bottom == 0)
                dp[i%2][j] = sum[(i-1)%2][top];
            else
                dp[i%2][j] = sum[(i-1)%2][top] - sum[(i-1)%2][bottom-1];
            if(bottom <= j-a[i] && j-a[i] <= top)
                dp[i%2][j] -= dp[(i-1)%2][j-a[i]];
            dp[i%2][j] /= m-1;

        }
        for(int j=i; j<=i*m+m; j++){
            sum[i%2][j] = sum[i%2][j-1] + dp[i%2][j];
        }
    }
    double ans = 0;
    for(int i=0; i<tot; i++){
        ans += dp[n%2][i];
    }
    printf("%.12lf\n",ans+1);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值