EDPC-J Sushi
まず状態数に着目すると、寿司1個の皿、2個の皿、3個の皿の数だけ注目すればいいので
期待値の問題は終了状態から再帰でdpをやるのが定石なのでする
:個の皿、個の皿、個の皿がそれぞれ枚の時の期待値
と置くと遷移は、zを0個の皿の数と置いて
確率:
確率:
確率:
確率:
なのでこれを無限ループにならないように無限和を扱いつつ書けばいい
以下,,をそれぞれと書くことにする
無限和の計算をいきなりすると頭が壊れるので丁寧に有限回の操作を計算する
回でから脱出する時の期待値は
回目で出る確率
回目以降の期待値
これをがからまで合算するから
あとは
・寿司のない皿から寿司を取らない
などに注意して実装する
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) using ld=long double; int v[4]; ld n,dp[301][301][301]; ld f(int a,int b,int c){ if(dp[a][b][c]>=0)return dp[a][b][c]; ld res=0,z=n-a-b-c; if(a)res+=a*f(a-1,b,c); if(b)res+=b*f(a+1,b-1,c); if(c)res+=c*f(a,b+1,c-1); res*=1/(n-z); res+=(a+b+c)*n/((n-z)*(n-z)); return dp[a][b][c]=res; } int main(){ cin>>n; REP(i,n-0.1){int x;cin>>x;v[x]++;} REP(i,301)REP(j,301)REP(k,301)dp[i][j][k]=-1; dp[0][0][0]=0; cout<<fixed<<setprecision(12)<<f(v[1],v[2],v[3])<<endl; }