AT_dp_j Sushi题解

题目描述

有 N 个盘子。每个盘子编号为 1,2,…,N。最初,对于每个 i(1≤i≤N),第 i 个盘子上有 ai​(1≤ai​≤3)个寿司。

太郎君会不断重复以下操作,直到所有寿司都被吃完:

  • 掷一个等概率出现 1,2,…,N 的骰子,掷出的点数为 i。如果第 i 个盘子上还有寿司,则吃掉一个寿司;如果没有寿司,则什么也不做。

请你求出吃完所有寿司所需操作次数的期望值。

输入格式

输入从标准输入按以下格式给出。

N a1​ a2​ … aN​

输出格式

输出吃完所有寿司所需操作次数的期望值。如果相对误差不超过 10−9,则视为正确。

显示翻译

题意翻译

输入输出样例

输入 #1复制

3
1 1 1

输出 #1复制

5.5

输入 #2复制

1
3

输出 #2复制

3

输入 #3复制

2
1 2

输出 #3复制

4.5

输入 #4复制

10
1 3 2 3 3 2 3 2 1 3

输出 #4复制

54.48064457488221

说明/提示

限制条件

  • 输入均为整数。
  • 1≤N≤300
  • 1≤ai​≤3

样例解释 1

吃掉第一个寿司所需操作次数的期望为 1。之后,吃掉第二个寿司所需操作次数的期望为 1.5。再之后,吃掉第三个寿司所需操作次数的期望为 3。因此,总的操作次数期望为 1+1.5+3=5.5。

样例解释 2

例如,输出 3.003.0000000032.999999997 等也可以被判定为正确。

由 ChatGPT 4.1 翻译

思路

概率期望DP。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long a[305],b[4];
double  n,f[305][305][305],lk=0;
int main(){
	cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[a[i]]++;
    }
    sort(a+1,a+(long)n+1);
    f[b[1]][b[2]][b[3]]=0;
    for(int k=0;k<=n;k++){
        for(int j=0;j<=n;j++){
            for(int i=0;i<=n;i++){
                if(i!=0||j!=0||k!=0){
                    if(i!=0){
                        f[i][j][k]+=(double)f[i-1][j][k]*i/(i+j+k);
                    }
                    if(j!=0){
                        f[i][j][k]+=(double)f[i+1][j-1][k]*j/(i+j+k);
                    }
                    if(k!=0){
                        f[i][j][k]+=(double)f[i][j+1][k-1]*k/(i+j+k);
                    }
                    f[i][j][k]+=(double)n/(i+j+k);
                }
            }
        }
    }
    printf("%.15lf\n",f[b[1]][b[2]][b[3]]);
	return 0;
}

posted @ 2025-10-22 21:06  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源