結果
問題 | No.108 トリプルカードコンプ |
ユーザー | codershifth |
提出日時 | 2015-08-13 01:01:37 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 8 ms / 5,000 ms |
コード長 | 2,996 bytes |
コンパイル時間 | 1,437 ms |
コンパイル使用メモリ | 165,200 KB |
実行使用メモリ | 11,624 KB |
最終ジャッジ日時 | 2024-07-18 07:03:25 |
合計ジャッジ時間 | 2,229 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 4 ms
11,572 KB |
testcase_01 | AC | 4 ms
11,504 KB |
testcase_02 | AC | 4 ms
11,516 KB |
testcase_03 | AC | 4 ms
11,484 KB |
testcase_04 | AC | 3 ms
11,272 KB |
testcase_05 | AC | 4 ms
11,392 KB |
testcase_06 | AC | 4 ms
11,336 KB |
testcase_07 | AC | 8 ms
11,624 KB |
testcase_08 | AC | 4 ms
11,548 KB |
testcase_09 | AC | 3 ms
11,276 KB |
testcase_10 | AC | 3 ms
11,548 KB |
testcase_11 | AC | 4 ms
11,568 KB |
testcase_12 | AC | 4 ms
11,396 KB |
testcase_13 | AC | 5 ms
11,496 KB |
testcase_14 | AC | 5 ms
11,344 KB |
testcase_15 | AC | 4 ms
11,396 KB |
testcase_16 | AC | 4 ms
11,460 KB |
testcase_17 | AC | 3 ms
11,276 KB |
testcase_18 | AC | 6 ms
11,388 KB |
testcase_19 | AC | 5 ms
11,396 KB |
testcase_20 | AC | 4 ms
11,336 KB |
testcase_21 | AC | 5 ms
11,396 KB |
testcase_22 | AC | 4 ms
11,396 KB |
ソースコード
#include <bits/stdc++.h> typedef long long ll; typedef unsigned long long ull; #define FOR(i,a,b) for(int (i)=(a);i<(b);i++) #define REP(i,n) FOR(i,0,n) #define RANGE(vec) (vec).begin(),(vec).end() using namespace std; class TripleCardComplete { public: // // カード枚数が 0 枚, 1 枚, 2 枚のカードの種類数を状態としてもつ DP でやる // // +-> Exp[a][b][c] -a のうちどれかが出る-> Exp[a-1][b+1][c] // | | | // | | +-------b のうちどれかが出る-> Exp[a][b-1][c+1] // +----+ | // +-------c のうちどれかが出る-> Exp[a][b][c-1] // int N; // 時間・空間計算量 O(10^6) double memo[101][101][101]; // カード枚数が 0 枚のものが a 種類残っている // カード枚数が 1 枚のものが b 種類残っている // カード枚数が 2 枚のものが c 種類残っている // ときからスタートしたときのカードをコンプリートするまで買うカードの期待値 double calc(int a, int b, int c) { if (memo[a][b][c] >= 0) // すでに計算済み return memo[a][b][c]; double res = 0.0; int total = a+b+c; if (total == 0) // 全て手に入った return memo[a][b][c] = 0.0; // a,b,c に含まれるカードたちのどれかが出る確率 double p = (double)total/N; double q = 1.0/p; // 結局自分自身から他へ遷移しないケース // a,b,c に含まれるカードたちが出る確率は p だった。 // これら以外が出るまでの試行回数の期待値は 1/p なのでこれを加える。 res += q; // 自己ループを複数回くりかえしてから別状態への遷移がある場合もあるので q 掛ける if (a) res += calc(a-1,b+1,c) * (double)a/N * q; // a のうちどれかが出るときの遷移 if (b) res += calc(a,b-1,c+1) * (double)b/N * q; // b のうちどれかが出るときの遷移 if (c) res += calc(a,b,c-1) * (double)c/N * q; // c のうちどれかが出るときの遷移 return memo[a][b][c] = res; } void solve(void) { cin>>N; vector<int> A(N); REP(i,101) REP(j,101) REP(k,101) memo[i][j][k] = -1; int n[3] = {0,0,0}; // n[i] := はじめに持っているカード枚数が i 枚のカードの種類総数 REP(i,N) { cin>>A[i]; if (A[i] < 3) ++n[A[i]]; } cout<<setprecision(20)<<calc(n[0],n[1],n[2])<<endl; } }; #if 1 int main(int argc, char *argv[]) { ios::sync_with_stdio(false); auto obj = new TripleCardComplete(); obj->solve(); delete obj; return 0; } #endif