面白い。けど問題文長い...。問題概要を短くまとめてみた。
問題概要
正の整数 が与えられる。
あなたは、 以上の整数を 個用意する ( とする)。この 個の整数のスコアを、以下の条件を満たす最小の整数 として定める。
- は のいずれでも割り切れない
個の整数 を適切に定めたときの、スコア の最大値を求めよ。
制約
考えたこと
であるとしよう。まず当然ながら
とするのがよい。さもなくばスコアは となってしまう。さて、もし ならばスコアは で確定となる。 ならば、次に
とするのがよい。以後同様に考えて、次のようにするのが最適となる。
すでに を決めたとき、これらの倍数とならない最小の整数を とする。このとき
と定めるのがよい。
実装
具体的に実装するにあたって、あらゆる状況におけるスコアの最大値として考えられる上限を としたとき、次のようなサイズ の配列を用意してあげる。
- iscovered[ v ] := v がいずれかの の倍数であるかどうか
の値を新しく定めるたびに
for (int y = x; y <= L; y += x) iscovered[y] = true;
という感じに更新してあげれば OK。これは存外計算量が少なくて の計算量となる。
L の見積もり
本来なら を見積る必要があるところだが、サンプルに答えが書いてある (実際の問題文でもそれを見るように誘導されている)。
であることがわかるので、これを使う。
コード
#include <bits/stdc++.h> using namespace std; const int MAX = 7500000; int solve(int M, int N) { vector<bool> iscovered(MAX, false); int x = M; for (int iter = 0; iter <= N; ++iter) { while (iscovered[x]) ++x; for (int y = x; y < MAX; y += x) iscovered[y] = true; } return x; } int main() { int M, N; while (cin >> M >> N, M) cout << solve(M, N) << endl; }