Hatena::Grouptopcoder

kojingharangの日記 RSSフィード

 | 

2015-04-19

SRM 656 Div1 250 RandomPancakeStack

01:18 |  SRM 656 Div1 250 RandomPancakeStack - kojingharangの日記 を含むブックマーク はてなブックマーク -  SRM 656 Div1 250 RandomPancakeStack - kojingharangの日記  SRM 656 Div1 250 RandomPancakeStack - kojingharangの日記 のブックマークコメント

  • パンケーキが N 個あり、パンケーキ i の直径は i+1 でおいしさは d[i] である。残ってるパンケーキから等確率で 1 個選びある皿に乗せていく。
  • 皿に乗ってる一番上のパンケーキの直径より大きなのが選ばれた時点で終了。取るやつがなくなっても終了。おいしさの期待値を求めよ。
  • 1≦N≦250, 1≦d[i]≦1000
  • DPが思いつかないので...
  • 1/N! の確率で [1, N] の permutation p が選ばれることになる。これを p[i-1]>p[i] である最大の i までについて Σd をとったものがその場合のおいしさ。
  • 縦に N! 通り、横に permutation を書いていってどうにか規則的に足せないか考えていると...
  • m+1 番目が X でありそれがおいしさにカウントされるような permutation の数は O(1) で求められることに気づく。
  • ? ? ? X ? ?
  • 前半は X より大きな N-x 個の数から m 個選び、後半は残りの N-m-1 個の順列なので Combination(N-x, m) * (N-m-1)!
  • というわけで、全 m, X についてその場合の数 * d[X] を足して最後に N! で割ったものが答え。
  • Accepted
  • dp でやる場合は dp[Topの直径][今まで何個使ったか], dp[N][0]=1, 配った時パンケーキごとに使った数を覚えていくとよい模様。
#define D long double

class RandomPancakeStack {
	public:
	D fac(int x) {
		D v = 1;
		REP(i, x) v*=i+1;
		return v;
	}
	D f(int x, int m, int N) {
		int k = N-m-1;
		if(N-x<m) return 0;
		return fac(N-x)*fac(k)/(fac(m)*fac(N-x-m));
	}
	double expectedDeliciousness(vector <int> d) {
		int N = d.size();
		D ans = 0;
		REP(v, N) {
			D lans = 0;
			REP(di, N) {
				D z = f(v+1, di, N);
				lans += z;
			}
			lans *= d[v];
			ans += lans;
		}
		D div = fac(N);
		return ans / div;
	}
};
 |