問題: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; }