SoundHound Inc. Programming Contest 2018 -Masters Tournament- のC問題解いた
問題:SoundHound Inc. Programming Contest 2018 -Masters Tournament- C - Ordinary Beauty
- 1~nの目のサイコロがある
- m回サイコロを振って、出た目を数列
とする
- 数列の隣り合う2項の差がdの個数を、その数列の美しさとする
- 数列の美しさの期待値
を求めよ
みたいな問題。
解説
- 隣り合う2項は
個ある
の
個
- 解説PDFにあるように、「期待値の線形性より、m-1通りそれぞれにおいて、差の絶対値がdである確率を求めて、全部足せばよい」
- ある隣り合う2項の美しさを
、その発生確率を
とすると、ある隣り合う2項の美しさの期待値は
である。
- 求めたい数列の期待値
は、
より、
となる。
- さらに
より、
となる。
- なので発生確率
を求めればよい
- 隣り合う2項を
と表したとき、この
と
の差の絶対値が
である(すなわち
である)発生確率
を求めたい。
のとき
- 美しさの条件を満たすのは
の
通り
- よって、発生確率
は
(分母の
は、aが
通り、bが
通りだから)
- 美しさの条件を満たすのは
のとき
- 美しさの条件を満たすのは
- の
通り
- よって発生確率
は、
- 美しさの条件を満たすのは
- これで求める期待値
が求まった。
実装
C++での解法です。
#include <bits/stdc++.h> #define _USE_MATH_DEFINES // M_PI等のフラグ #define MOD 1000000007 #define COUNTOF(array) (sizeof(array)/sizeof(array[0])) #define rep(i,n) for (int i = 0; i < (n); ++i) #define intceil(a,b) (a+(b-1))/b using namespace std; using ll = long long; using pii = pair<int,int>; using pll = pair<long,long>; const long long INF = LONG_LONG_MAX - 1001001001; void chmax(int& x, int y) { x = max(x,y); } void chmin(int& x, int y) { x = min(x,y); } void solve() { // 隣り合う2項はm-1通りある // 2項(a,b)のa,bの絶対値の差がdである確率を求めて、(m-1)倍すればよい ll n, m, d; cin >> n >> m >> d; double ans; if (d==0) { // (1,1),...(n,n)のn通り ans = (double)n/pow(n,2); ans *= (m-1); } else { // (1, 1+d), (2, 2+d), ..., (n-d, n) // (1+d, 1), (2+d, 2), ..., (n, n-d) の2(n-d)通り ans = (double)2*(n-d)/pow(n,2); ans *= (m-1); } printf("%.10lf", ans); } int main() { solve(); return 0; }