公式

F - 平均順位/Average Ranking 解説 by nok0


はじめに、これまでの試合の平均順位を計算します。このときの順位がすでに目標の値以下であれば、これ以上試合を行う必要はありません。

そうでない場合を考えます。平均順位の値がもっとも小さくなるのは、新しく行う試合の結果が全て 1 位のときです。

このとき、新しく何試合行う必要があるでしょうか?

目標の平均順位が \(y\)、現在の平均順位が \(x\) だとします。追加で \(k\)\(1\) 位を取ったときの平均順位は \(\frac{x \times n + k}{n+k}\) であり、これが \(y\) 以下である必要があります。この方程式を解くと、

\[\frac{x \times n + k}{n+k}\leq y\]

\[(x-y) n \leq (y-1)k \]

となるので、\((x-y)n\)\(y-1\) で切り上げ除算することで、最小の \(k\) が求められます。

なお、これらの計算を浮動小数点型で行うのは、誤差の関係で危険です。今回の場合、値を \(1000\) 倍することで全て整数で行うことができます。

実装例(c++):

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

int main() {
  ll n;
  cin >> n;
  ll sum = 0;
  for (int i = 1; i <= 4; i++) {
    ll a;
    cin >> a;
    sum += a * i;
  }
  sum *= 1000;
  string s;
  cin >> s;
  ll x1000 = (s[0] - '0') * 1000 + (s[2] - '0') * 100 + (s[3] - '0') * 10 +
             (s[4] - '0');
  ll y = x1000 * n;
  if (sum <= y) {
    cout << 0 << endl;
  } else {
    ll diff = sum - y;
    ll ch = x1000 - 1000;
    cout << (diff + ch - 1) / ch << endl;
  }
}

投稿日時:
最終更新: