-
C++で与えられた整数が3の累乗かどうかを判定する方法
この問題では、整数Nが与えられ、その整数が3の累乗であるかどうかを判定することが課題となります。問題の例具体的な例を見てみましょう。入力 : N = 729 出力 : Yes説明:36 = 729729は3の6乗に等しいため、3の累乗であると判定できます。解法のアプローチこの問題を効率的に解くには、3の累乗の性質を利用します。ポイントとなるのは、32ビット符号付き整数で表現できる最大の3の累乗は 1162261467(319) であるという点です。判定方法は非常にシンプルです。与えられた数Nが 1162261467 を割り切れるかどうか を確認します。もしNが3の累乗であれば、その約数はすべて
-
C++で与えられた整数が4の累乗かどうかを判定する方法
この問題では、整数 N が与えられ、その整数が4の累乗(べき乗)であるかどうかを判定することが求められます。問題の例入力:N = 64 出力:Yes解説:43 = 6464 は 4 を3回掛け合わせた数、つまり4の累乗なので「Yes」が出力されます。解法のアプローチ最もシンプルな解き方は、数値を繰り返し4で割っていく方法です。具体的な手順は以下の通りです。数値が0の場合は4の累乗ではないため false を返します。数値が1になるまでループを続け、各段階で4で割り切れるかどうかを確認します。途中で割り切れない場合は false を返します。最終的に1になれば、その数は4の累乗であるため tru
-
C++で部分配列が山型(マウンテン)かどうかを判定する方法
この記事では、整数配列 arr[] と範囲 [L, R] が与えられたとき、その範囲に含まれる部分配列が山型(マウンテン)の形になっているかどうかを判定する方法を解説します。「山型」とは、要素が途中まで単調に増加し、頂上から先は単調に減少していく、文字どおり山のような形状を持つ部分配列のことです。問題の確認具体例を見てみましょう。入力 : arr[] = {1, 4, 2, 5, 6, 7, 3, 0}, 範囲 = [2, 7] 出力 : Yes説明:範囲 [2, 7] の部分配列 = {2, 5, 6, 7, 3, 0} 値がまず増加し、その後減少しているため山型です。解法アプローチこの問題
-
【C++】ある配列が別の配列の部分集合(サブセット)かどうかを判定する5つの方法
問題の概要この問題では、サイズ m の整数型配列 arr1[] と、サイズ n の整数型配列 arr2[] が与えられます。求めたいのは、「arr2 が arr1 の部分集合(サブセット)であるかどうか」の判定です。なお、両方の配列は順序がバラバラで、要素に重複はないものとします。入力例Input : arr1[] = {5, 2, 1, 6, 8, 10}, arr2[] = {6, 2, 1} Output : arr2 is a subset of arr1.解決アプローチこの問題は複数の手法で解くことができます。ここでは代表的な5つの方法を、それぞれの仕組みと実装例とあわせて解説します
-
C++でax + by = nを満たすxとyを求める方法
この問題では、3つの整数値 a、b、n が与えられます。私たちのタスクは、ax + by = n を満たす x と y を見つけることです。問題の理解まず、具体例を見て問題を把握しましょう。入力 : a = 4, b = 1, n = 5出力 : x = 1, y = 1この場合、4 × 1 + 1 × 1 = 5 となり、確かに方程式を満たしています。解法のアプローチこの問題に対するシンプルな解決策は、0 から n までの範囲で方程式を満たす値を順に探していくことです。これを実現するために、方程式を次のように変形します。x = (n − by) / ay = (n − ax) / bx の候
-
C++で「2/n = 1/x + 1/y + 1/z」を満たすx、y、zを見つける方法
この問題では、整数値 n が与えられ、「2/n = 1/x + 1/y + 1/z」を満たす x、y、z を見つけることが課題となります。 例で問題を理解しよう 入力 : n = 4出力 : 4, 5, 20 解法アプローチ この問題に対するシンプルな解決策は、n の値をもとに解を直接導き出すことです。 n = 1 の場合:方程式の解は存在しません。 n > 1 の場合:解は x = n、y = n+1、z = n(n+1) となります。 この解が正しいことは、次の等式から確認できます。 2/n = 1/n + 1/(n+1) + 1/(n×(n+1)) 右辺を通分して計算すると、次
-
C++でXOR演算子を使わずに2つの数値のXORを求める方法
この問題では、2つの整数値 A と B が与えられ、XOR演算子(^)を使用せずに両者のXORを求めることが課題となります。具体例で問題を確認してみましょう。入力 : A = 4, B = 5出力 : 1解法アプローチ1:ビットごとの演算を利用するまず、各数値を2進数に変換し、次の真理値表に基づいてビット単位の演算を行う方法があります。AB出力000011101110この表は、両方のビットが同じ場合に0、異なる場合に1を返す、まさにXORの動作そのものです。AND・OR・NOTなどの基本的なビット演算だけを組み合わせることで、この結果を実現できます。実装例上記の解法の動作を示すプログラムです。
-
C++で一方の数値のセットビットに対応して他方の数値のビットを反転する方法
問題概要 本記事では、2つの整数値が与えられたときに、「一方の数値のセットビット(1となっているビット)の位置に対応して、もう一方の数値のビットを反転(トグル)する」という操作を実現するC++プログラムを紹介します。 問題の理解 まず、具体例を使って問題内容を確認しましょう。 入力: 3 7 出力: 4 3の2進数表現: 011 7の2進数表現: 111 数値「3」は2進数で「011」と表されるため、下位から0桁目と1桁目がセットビットです。そこで、もう一方の数値「7」(2進数で「111」)の対応するビット、すなわち0桁目と1桁目を反転します。その結果は「100」となり、10進数では「4」に
-
フラッドフィルアルゴリズムとは?C++でペイントの塗りつぶし(fill)機能を実装する方法
問題概要 この問題では、2次元画面を表す2次元配列と、色を塗りたいピクセルの座標、そして新しい色が与えられます。私たちのタスクは、指定されたピクセルと、そのピクセルと同じ色を持つすべての隣接ピクセルを新しい色で塗りつぶすプログラムを作成することです。 これは、お絵かきソフト(ペイント)でバケツツールを使う操作に相当します。好きな色を選び、ブラシで目的のピクセルをクリックすると、つながっている同じ色の領域全体が一気に塗り替えられるのです。 具体例で問題を理解しよう 入力:Screen[][] = {{W, W, B, W, W, W, W, W}, {W, W, W, W, W, W, B,
-
【C++】最大1回のスワップ操作で作れる最大の数を求める方法
この問題では、正の整数が1つ与えられます。求められているのは、最大で1回のスワップ(桁の入れ替え)操作を使って、可能な限り大きな数を作り出すプログラムを書くことです。 新しい数は、元の数を構成する桁を並べ替えて作成します。ただし、入れ替えてよいのは1箇所のみです。 問題を理解するための例 入力: n = 63512 出力: 65312 上の例では、2桁目の「3」と3桁目の「5」を入れ替えることで、65312という最大の数が得られます。 解法アプローチ1:すべてのスワップを試す方法 最もシンプルな方法は、与えられた数の桁のペアを入れ替えることで作れるすべての数を列挙し、その中から最大のものを返
-
【C++】最大1回のスワップ操作で最小の数を作る方法を解説
問題概要この問題では、正の整数が1つ与えられます。求められているのは、最大でも1回のスワップ(桁の入れ替え)操作を使って、その数字の桁から作れる最小の数を作るプログラムです。つまり、既存の数の桁を使って新しい数を作りますが、許されるのは元の数からの1箇所だけの入れ替えです。例で問題を確認しよう入力:n = 63519出力:36519この例では、先頭の「6」と2番目の「3」を入れ替えることで、63519 より小さい 36519 を作れています。解法アプローチ①:すべてのスワップを試す(全探索)最もシンプルな方法は、与えられた数の桁のペアを入れ替えて作られるすべての数を列挙し、その中で最小のものを
-
C++で数列3、13、42、108、235…のn番目の項を求める方法
この問題では、整数 n が与えられます。求めるのは、数列「3, 13, 42, 108, 235, ...」の n番目の項です。問題の理解まず、具体的な例で問題を確認しましょう。入力 : 5 出力 : 235解法アプローチこの数列は、「最初のn個の自然数の立方数の和」に「2 × n」を加えた値として表すことができます。最初のn個の自然数の立方数の和は、有名な公式 (n × (n + 1) / 2)2 で求められます。したがって、この数列の第n項を求める公式は次のようになります。第n項 = (n × (n + 1) / 2)2 + 2 × n計算例(n = 5 の場合)(5 * (5 + 1)
-
C++でn!に含まれる素数pの冪指数を求める方法
問題概要この問題では、数値 n と素数 p が与えられます。求めるのは、n!(nの階乗)に含まれる素数pの冪指数、つまり n! を素因数分解したときに p が何回掛けられているかです。具体例で確認してみましょう。入力 : n = 6, p = 2出力 : 4この場合、6! = 720 であり、その素因数分解は次のようになります。720 = 2 × 2 × 2 × 2 × 3 × 3 × 52の個数は4つなので、出力は 4 となります。解決アプローチ(ルジャンドルの公式)最も単純な解法は、実際に n! の値を計算して素因数分解することですが、n が大きくなると階乗の値は爆発的に増大するため現実的
-
C++で数値の上位3ビットと下位3ビットを10進数に変換する方法
問題概要 本記事では、整数 N が与えられたときに、その2進表現における上位3ビットと下位3ビットをそれぞれ10進数に変換して求める問題を扱います。 まず、具体例で問題を確認しましょう。 入力:57 出力:7 1 57 を2進数に変換すると「111001」になります。上位3ビットは「111」で10進数の 7、下位3ビットは「001」で10進数の 1 に対応するため、出力は「7 1」となります。 解法のアプローチ 最もシンプルな解き方は、次の手順に従うものです。 数値 n を2進数に変換し、各ビットを配列に保存する。 配列の中から上位3ビットと下位3ビットを取り出す。 それぞれのビット列を独
-
C言語のサンプルコードで学ぶフォーマット文字列脆弱性とその防止策
フォーマット文字列(Format String)とは、文字列を整形(フォーマット)するために使用されるASCII文字列のことです。テキストと書式指定パラメータ(フォーマット指定子)を組み合わせて構成されます。C言語には、プログラムの出力を整形するために、さまざまなフォーマット文字列が用意されています。フォーマット文字列脆弱性とはフォーマット文字列脆弱性とは、プログラマが陥りやすいプログラミング上のミスによって発生するバグです。攻撃者が入力した文字列がそのまま printf や sprintf などの出力関数に渡されると、任意のメモリアドレスへの書き込み操作が行われる可能性があります。これにより
-
C++でガウス・ジョルダン法を使って行列の逆行列を求める方法
この問題では、2次元行列 mat[][] が与えられ、ガウス・ジョルダン法(Gauss-Jordan Method)を用いて行列の逆行列を求めることが課題となります。 まず、問題を理解するための基礎知識から確認していきましょう。 行列(MATRIX)とは、数値を2次元配列の形に並べたものです。 例 $\begin{bmatrix}2&5&4 \\1&6&7 \\9&3&8\end{bmatrix}$ 逆行列 [A-1]とは、正方行列に対して行われる演算のひとつです。行列が逆行列を持つためには、次の条件を満たす必要があります。 元の行列が正方行列
-
C++でソート済み連結リストから中央値を求める方法
この問題では、N個の要素からなるソート済み連結リスト(ソートされたリンクリスト)が与えられ、その中央値を求めることが課題となります。ソート済み連結リストと中央値とはソート済み連結リストとは、すべての要素が特定の順序で並べ替えられたシンプルな連結リストのことです。例: 4 -> 6 -> 7 -> 9 -> NULL中央値は、連結リストの中央に位置する要素です。求め方は以下の通りです。Nが奇数の場合:中央値は (n/2) 番目の要素Nが偶数の場合:中央値は (n/2) 番目の要素と (n/2 + 1) 番目の要素の平均値具体例で理解しよう入力: 2 -> 3 -&g
-
C++で素数の数字(2・3・5・7)のみで構成されるn番目の数を効率的に求める方法
この記事では、整数Nが与えられたときに、「素数の数字(2、3、5、7)のみで構成される数列」のN番目の数を求めるアルゴリズムを解説します。 素数の数字だけで構成される数列は、次のように並びます。 2, 3, 5, 7, 22, 23, 25, 27, 32, 33, ... 問題を理解するための例 入力:N = 6 出力:23 この場合、数列の6番目の要素は「23」となるため、出力は23です。 解法のアプローチ この問題を解くシンプルな方法は、数列の規則性を観察することです。まず、与えられたインデックスNに対応する項を見つけることを考えます。 使用できる数字が4種類(2、3、5、7)しかない
-
C++で解く「友達ペアリング問題」|動的計画法・再帰メモ化・空間最適化の3つの実装
C++ を使って「友達ペアリング問題(Friends Pairing Problem)」を解くプログラムを作成します。この問題では、グループ内の友人の人数を表す正整数 N が与えられます。 各友人には次の2つの選択肢があります。 誰ともペアを組まずに単独で残る グループ内の別の友人1人とペアを組む(各友人がペアを組めるのは一度だけ) 問題の例 具体例で問題を確認してみましょう。 入力: n = 3 出力: 4 説明: グループの3人を A、B、C とすると、組み合わせ方は以下の4通りです。 {A}, {B}, {C} {A, B}, {C} {A, C}, {B} {A}, {B, C}
-
C++で全要素が等しい最大の正方形部分行列を求めるアルゴリズム
問題概要この問題では、N×N の行列 mat[] が与えられ、すべての要素が等しい最大の正方形部分行列を見つけることが課題となります。つまり、与えられた行列の中から、全要素が同じ値で構成される正方形部分行列のうち、最大のサイズを求める必要があります。問題を理解するための具体例入力: mat[][] = {{1, 2, 1}, {1, 2, 2}, {2, 2, 2}} 出力: 2説明:a11, a12, a21, a22 の位置にある要素は 2×2 の正方形を形成し、すべて同じ値(2)で構成されています。解法アプローチ単純な解法(総当たり): 行列のすべての要素を走査し、考えられるすべての部分