[DP]確率\(P2059 \)カードゲーム
タイトル説明
\(N \)個人がゲームをプレイサークルに座っています。まずはから時計回りに、すべてのプレーヤーを置く\(1 \)する(N \)\数を。最初のラウンドは、第1選手です\(1 \)ディーラーとして。各ラウンドは、カードの山からカードを選択する(つまり、同じ確率で、ある)ランダム作るためのカードの数字と仮定されます\(X- \)は、すべてのプレイヤーに見せるためにカード上の最初の番号を作り、を押し数のディーラー位置から時計回りに\(X \)個人がゲームを終了するために実行されます。その後、カードはカードや改造の山に戻されます。時計回りにディーラーの次のラウンドとなる次の人によって実行された方。そして、後に(N-1 \)\最後のラウンドの後は一人だけを残して、このゲームは勝者です。今、あなたが事前に知っている合計\(M \)カードは、各カードにその番号を知っています。今、あなたは、各プレイヤーの勝利の確率を決定する必要があります。
入力形式
最初の行は二つの整数含む\(N、M \)をそれぞれ表す数と選手カードの総数。
次の行を含む\(M \)整数は、それぞれのカードに書かれた番号を与えます。
出力フォーマット
含む出力ライン(N \)\小数点以下に与えられたパーセント数の形で固体。プレイヤーは別に与えられた\(1 \)プレイヤーに\(N \)の勝利確率、スペースで区切ってそれぞれの間の確率、そして最後にスペースなし。
サンプル ]
5 5
2 3 5 7 11
22.72% 17.12% 15.36% 25.44% 19.36%
4 4
3 4 5 6
25.00% 25.00% 25.00% 25.00%
以下のために(30 \)\データの%、ある(1 \当量のNの\の当量\ 10 \)は
以下のために(50 \)\データの%、ある(1 \当量のNの\の当量\ 30 \)は
以下のために(100 \)\データの%、ある\(1 \当量N \の当量 50、1 \当量M \の当量50、1 \当量の\) 各カードの数字(\ \当量50 \)
\(溶液\)
実際には、この質問は、私はすべてのことを考え始めました。考え始め、検索ですが、それはたくさんのことを記録しているようだ、私は転送が実行可能ではないと思いました。それは......後方検索しますか?
セット([I] [J F \ ] \) 持っている\(私は\)個々の時間、\(j個\)個人的な勝利の確率。確率を加えることができるので、それは押し戻さすることができます。
どのように転送するには?手は、それがことがわかった(私は\)\描かれたディーラーのカードは、個人の場合には\(k個\) 、そして- \(1 \ⅰ)個人的な最初の\(J \)個人的な位置である......カテゴリー話。もし<\(K J \)、\ - (K \ J = J) 、もし(J \ \ K)>、\ (J = I - K + J \) 、あれば\(K = J \) 、しませんので、考える\(jは\)が死亡しました。
だから、長い間遷移方程式:
int p = a[k] % i == 0? i:a[k] % i;
if(p > j) f[i][j] += f[i - 1][i - p + j] / m;
else if(p < j) f[i][j] += f[i - 1][j - p] / m;
\(それは\ ~~すべてです)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
long long read(){
long long x = 0; int f = 0; char c = getchar();
while(c < '0' || c > '9') f |= c == '-', c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return f? -x:x;
}
int n, m, a[57];
double f[57][57];
int main(){
n = read(); m = read();
for(int i = 1; i <= m; ++i) a[i] = read();
f[1][1] = 1.0;
for(int i = 2; i <= n; ++i)
for(int j = 1; j <= i; ++j)
for(int k = 1; k <= m; ++k){
int p = a[k] % i == 0? i:a[k] % i;
if(p > j) f[i][j] += f[i - 1][i - p + j] / m;
else if(p < j) f[i][j] += f[i - 1][j - p] / m;
}
printf("%.2lf%%", f[n][1] * 100);
for(int i = 2; i <= n; ++i) printf(" %.2lf%%", f[n][i] * 100);
return 0;
}