Official

E - Dice Product 3 Editorial by en_translator


Consider solving this problem with a DP (Dynamic Programming). Let

\(\mathrm{dp}(n)\): (the probability that your integer results being \(N\), starting from the state where the your integer is \(n\));

then the answer is \(\mathrm{dp}(1)\).

We find the equation on \(\mathrm{dp}(n)\). When you cast a die, your integer changes to one of \(n, 2n, 3n, 4n, 5n, 6n\) with equal probabilities. Thus

\[\mathrm{dp}(n) = \frac{1}{6} (\mathrm{dp}(n) + \mathrm{dp}(2n) + \mathrm{dp}(3n) + \mathrm{dp}(4n) + \mathrm{dp}(5n) + \mathrm{dp}(6n) ).\]

This equation contains \(\mathrm{dp}(n)\), so we eliminate them:

\[\mathrm{dp}(n) - \frac{1}{6} \mathrm{dp}(n) = \frac{1}{6} (\mathrm{dp}(2n) + \mathrm{dp}(3n) + \mathrm{dp}(4n) + \mathrm{dp}(5n) + \mathrm{dp}(6n) )\]

\[\frac{5}{6} \mathrm{dp}(n) = \frac{1}{6} (\mathrm{dp}(2n) + \mathrm{dp}(3n) + \mathrm{dp}(4n) + \mathrm{dp}(5n) + \mathrm{dp}(6n) )\]

\[\mathrm{dp}(n) = \frac{1}{5} (\mathrm{dp}(2n) + \mathrm{dp}(3n) + \mathrm{dp}(4n) + \mathrm{dp}(5n) + \mathrm{dp}(6n) )\]

Now we have an equation regarding \(\mathrm{dp}(n)\).

Also, \(\mathrm{dp}(N) = 1\), and \(\mathrm{dp}(n) = 0\) for \(n \geq N\). Using these properties, we can see that computing \(\mathrm{dp}(n)\) with a memorized recursion terminates in a finite time.

  • The left hand side is an equation about \(\mathrm{dp}(n)\), while the right hand side is about \(\mathrm{dp}(kn)\) \((2 \leq k \leq 6)\), so the deeper the recursion is, the larger the argument is. Thus, the recursion never triggers a loop.

We estimate the complexity. Let \(X\) be the number of distinct integers that can be an argument \(n\) of \(\mathrm{dp}(n)\); then, the memorized recursion using std::map is estimated to be work in a total of \(\mathrm{O}(X \log X)\), so we evaluate the upper bound of \(X\).
The die shows only multiples of \(2, 3, 5\), so \(n\) can always be represented as \(n = 2^a 3^b 5^c\) with non-negative integers \((a, b, c)\). With \(n \leq N\), we have

\[ \begin{aligned} &0 \leq a \leq \log_2 N \leq \log_2(10^{18}) < 60 \\ &0 \leq b \leq \log_3 N \leq \log_3(10^{18}) < 38 \\ &0 \leq c \leq \log_5 N \leq \log_5(10^{18}) < 26, \end{aligned} \]

so there are at most \(60 \times 38 \times 26 = 59280\) distinct integers that can be \(n\). Hence, \(X \leq 59280\) is proven, and the DP with the memorized recursion works fast enough.

  • Sample code (C++)
#include <iostream>
#include <map>
using namespace std;
#include "atcoder/modint.hpp"
using mint = atcoder::modint998244353;

long long N;
map<long long, mint> memo;
mint dp(long long n) {
  if (n >= N) return n == N ? 1 : 0;
  if (memo.count(n)) return memo[n];
  mint res = 0;
  for (int i = 2; i <= 6; i++) res += dp(i * n);
  return memo[n] = res / 5;
}
int main() {
  cin >> N;
  cout << dp(1).val() << "\n";
}

posted:
last update: