C++で解く:数値nから到達できる最小値を求めるゲーム問題
数値 n が与えられます。ゲーム開始時点での n の値は v であり、プレイヤーは次の操作を0回以上繰り返し実行できます。
操作: 正の整数 x(x < n かつ x が n の約数ではない)を選び、n から x を引く。
プレイヤーの目標は、最終的な n の値を最小化することです。
例えば、入力が n = 8 の場合、出力は 1 になります。最初の手番で x = 3 を選ぶと n は 5 になり、続いて x = 4 を選ぶことで n = 1 を達成できるためです。
解法の考え方
この問題は一見複雑に思えますが、実は非常にシンプルな規則性があります。
- n = 2 の場合: x < 2 を満たす正の整数は x = 1 のみですが、1 は 2 の約数であるため、操作を実行できません。よって答えは 2 となります。
- n ≥ 3 の場合: x = n − 1 を選べば必ず操作が可能です。n − 1 は n より小さく、n の約数にはなり得ない(n の約数で n/2 より大きいものは n 自身のみ)ためです。これにより n は 1 になります。
以上より、アルゴリズムは次のようにまとめられます。
if n が 2 と等しい場合:
return 2
return 1実装例
理解を深めるために、以下のC++による実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
int solve(int n){
if (n == 2){
return 2;
}
return 1;
}
int main(){
int n = 8;
cout << solve(n) << endl;
}入力
8
出力
1
このように、約数の性質に着目することで、一見探索が必要な問題も O(1) の定数時間で解くことができます。
-
C++でNからMに到達するまでの最小ステップ数を求める方法
2つの整数NとMが与えられたとき、以下の2種類の操作のみを使ってNからMに到達するために必要な最小ステップ数を求める問題について解説します。数xを2倍にする(xは2*xになる)数xから1を引く(xはx−1になる)例えば、N = 4、M = 6の場合、答えは2になります。まずNに対して「1を引く」操作を行うと3になり、続けて「2倍する」操作を行うと2 * 3 = 6となり、Mに到達できます。したがって、必要な最小ステップ数は2です。解法のアプローチ:問題を逆転させるこの問題を効率的に解く鍵となるのは、問題を逆向きに考えることです。NからMへ向かう代わりに、MからNへ向かうと考え直すと、操作は次の
-
【C++】素因数分解で約数の和の最小値を求めるアルゴリズムを解説
約数の和の最小値を求める問題とは この記事では、与えられた整数の「約数の和の最小値」を求めるアルゴリズムを、C++で実装しながら解説します。 例として、数12を考えてみましょう。12は以下のように複数の方法で因数分解できます。 12 = 12 × 1 → 和は 12 + 1 = 13 12 = 2 × 6 → 和は 2 + 6 = 8 12 = 3 × 4 → 和は 3 + 4 = 7 12 = 2 × 2 × 3 → 和は 2 + 2 + 3 = 7 この中で最小となる和は7です。本記事では、任意の整数nが与えられたとき、この最小の和を効率よく求める方法を紹介します。 アプローチ:素因数