-
【C++】配列のビットごとのORを最大化するアルゴリズム
問題の概要 N個の整数からなる配列が与えられます。ここで、配列内の任意の1つの要素に対して、指定された整数 x を最大 k 回まで乗算するという操作を一度だけ行い、配列全体のビットごとのOR(論理和)を最大化することを考えます。 たとえば、入力配列が {4, 3, 6, 1}、k = 2、x = 3 の場合、得られる最大値は 55 となります。これは、要素「6」に 3^2 = 9 を掛けて 54 とし、残りの要素 {4, 3, 1} とのORを取ると 54 | 4 | 3 | 1 = 55 になるためです。 アルゴリズム どの要素を何倍すればよいかを毎回総当たりで調べるのは非効率です。そこで
-
C++で最大1要素を削除した後の部分配列の最大和を最大化する方法
問題文N個の整数からなる配列 arr[] が与えられます。まず最大部分配列和を求め、その部分配列から最大で1つの要素を削除したとき、合計が最大になるようにします。つまり、削除できる要素は最大で1つまでとし、削除後の合計を最大化することがこの問題の目的です。例として、入力配列が {1, 2, 3, -2, 3} の場合を考えてみましょう。この配列の最大部分配列は配列全体 {1, 2, 3, -2, 3} で、その和は7です。ここで -2 を削除すると、残りの配列は次のようになります。{1, 2, 3, 3} となり、和は9でこれが最大となります。アルゴリズムこの問題は、カダネのアルゴリズム(Ka
-
C++で配列の中央値を最大化する方法を解説
問題の概要N個の要素を含む配列 arr[] と整数 K(K < N)が与えられます。求められているのは、この配列にK個の整数要素を挿入し、結果として得られる配列の中央値を最大化することです。例として、入力配列が {1, 3, 2, 5}、k = 3 の場合を考えてみましょう。配列をソートすると {1, 2, 3, 5} になります最大値の5より大きい要素を3つ挿入します。この操作により、配列は {1, 2, 3, 5, 6, 6, 6} になります新しい配列の中央値は 5 となりますアルゴリズムの考え方この問題を解くためのポイントは、以下の2点です。挿入する要素の選び方: 中央値を最大化
-
C++で配列にK個の要素を追加した後に中央値を最大化する方法
問題概要N個の要素からなる配列 arr[] と整数 K(K < N)が与えられます。この配列に K 個の整数要素を挿入し、結果として得られる配列の中央値を最大化することが課題です。例として、入力配列が {1, 3, 2, 5}、k = 3 の場合を考えてみましょう。配列をソートすると {1, 2, 3, 5} になります最大値 5 より大きい要素を 3 つ挿入します。操作後の配列は {1, 2, 3, 5, 6, 6, 6} になります新しい配列の中央値は 5 となりますアルゴリズムこの問題を解くための手順は以下の通りです。結果の配列の中央値を最大化するには、挿入するすべての要素が元の配列の最
-
C++でビットを再配置して最大の数を作る方法
問題文符号なし整数が与えられたとき、その数が持つビットを並べ替えて作ることができる最大の数を求めます。たとえば、入力が 8 の場合、その2進数表現は次のようになります。00000000000000000000000000001000この数を最大化するには、最上位ビット(MSB)を1にします。すると数は 2147483648 となり、その2進数表現は次のとおりです。10000000000000000000000000000000アルゴリズム与えられた数の2進数表現におけるセットビット(1になっているビット)の個数 n を数える下位 n ビットがすべて1になる数を作るその数を (32 − n) ビ
-
C++で長さp、q、rのセグメント数を最大化する方法
問題文長さ L の棒が与えられます。この棒を、長さ p、q、r のセグメントの合計数が最大になるように切断することが課題です。セグメントの長さとして許されるのは p、q、r のみです。例えば、l = 15、p = 2、q = 3、r = 5 の場合、次のように7個のセグメントを作ることができます。{2, 2, 2, 2, 2, 2, 3}アルゴリズムこの問題は動的計画法(DP)を使って効率的に解くことができます。各位置において「そこまで到達できるか」「到達できるなら最大何回の切断が可能か」を順に求めていくのがポイントです。dp[] 配列を初期化します。まだ到達できない位置を表すため -1 で埋
-
C++でarr[i]*iの合計を最大化する方法
問題の概要N個の整数からなる配列が与えられます。配列の要素は自由に並べ替えることができます。そのうえで、Σarr[i] * i(i = 0, 1, 2, ... n-1)の最大値を求めるのが課題です。例えば、入力配列が {4, 1, 6, 2} の場合、要素を昇順に並べ替えることで最大値28が得られます。{1, 2, 4, 6} = (1 * 0) + (2 * 1) + (4 * 2) + (6 * 3) = 28アルゴリズムこの問題は、次の手順で解くことができます。配列を昇順にソートする配列を走査し、各要素にインデックスi(0, 1, 2, ..., n-1)を掛けて合計する合計値を返すな
-
C++で3つの整数から式の最大値を求める方法
問題文0でない3つの整数 a、b、c が与えられます。この3つの整数の間に「加算(+)」と「乗算(*)」の記号を任意の順序で1回ずつ挿入し、式が取り得る最大の値を求めることが課題です。なお、整数同士の並べ替え(順序の入れ替え)は自由に行って構いませんが、加算記号と乗算記号は必ずそれぞれ1回ずつ使用しなければなりません。例えば、a = 1、b = 3、c = 5 の場合、最大値は次のようにして 20 になります。(1 + 3) * 5 = 20アルゴリズム最大値は、入力される整数の中に負の数がいくつ含まれているかによって場合分けすることで、効率的に求めることができます。すべての数が正の場合:小さ
-
C++で配列の (arr[i] − i) − (arr[j] − j) の値を最大化する方法
問題文 配列 arr[] が与えられたとき、i ≠ j となる条件のもとで、(arr[i] − i) − (arr[j] − j) の最大値を求めます。ここで、i と j は 0 から n−1 までの範囲をとり、n は入力配列 arr[] のサイズです。 例えば、入力配列が {7, 5, 10, 2, 3} の場合、次のように計算することで最大値 9 を得られます。 (要素10 − インデックス2) − (要素2 − インデックス3) (10 − 2) − (2 − 3) = 8 − (−1) = 9 考えるポイント (arr[i] − i) − (arr[j] − j) を最大化するには、
-
C++でソート済みの2つの配列からxに最も近い合計値を持つペアを見つける方法
ソート済みの2つの配列と数値 x が与えられたとき、合計が x に最も近くなるペアを見つける必要があります。このペアは、それぞれの配列から1つずつの要素を組み合わせたものです。具体的には、配列 A1[0..m-1] と A2[0..n-1]、および目標値 x が与えられ、|A1[i] + A2[j] − x| の絶対値が最小となるような A1[i] + A2[j] の組み合わせを求めます。例えば、A1 = [1, 4, 5, 7]、A2 = [10, 20, 30, 40]、x = 32 の場合、出力は「1 と 30」になります(1 + 30 = 31 が x = 32 に最も近いため)。アル
-
C++で2つの配列間の互換性の差を求める方法
問題の概要 2人の友人が、お互いの相性を確かめたいと考えています。そこで、1からnまでの番号が付けられた映画を、それぞれが好みに応じてランク付けします。このとき求めるのが、2人の間の「互換性の差」です。 互換性の差とは、同じ映画に対する2人の相対的な順位付けがどれだけ食い違っているかを表す数値のことです。たとえば、A = [3, 1, 2, 4, 5]、B = [3, 2, 4, 1, 5] という2つの順位リストが与えられた場合、出力は 2 になります。これは、友人Aが映画1を映画2や4よりも上位にランク付けしている一方で、友人Bはそれらより下位にランク付けしているためです。 アルゴリズムの
-
C++で「using namespace std;」を使うべきではない理由と名前空間汚染のリスク
C++における名前空間の基本C++では、コードを整理し名前の衝突を防ぐために「名前空間(namespace)」という仕組みが用意されています。開発者が独自の名前空間を定義することもできますが、最もよく知られているのは、C++標準ライブラリが提供する「std」という名前空間です。多くの入門書やサンプルコードでは、以下のような記述を目にするでしょう。using namespace std;std名前空間の役割標準ライブラリには、コンテナ(vectorやmapなど)、アルゴリズム、入出力ストリームなど、アプリケーション開発で頻繁に使われる機能が多数含まれています。もしこれらの名前がグローバル空間に直
-
【C++】コンストラクタのオーバーロードとは?基本ルールと実装例を解説
オブジェクト指向言語の中核機能のひとつに「関数のオーバーロード」があります。これは、引数の数や型が異なっていれば、同じ名前の関数を複数定義できる仕組みです。本記事では、このオーバーロードをクラスのコンストラクタに適用する「コンストラクタのオーバーロード」について、その考え方と具体的な実装方法を解説します。 コンストラクタオーバーロードの重要ポイント コンストラクタをオーバーロードする際は、次の3つのポイントを押さえておきましょう。 オーバーロードされたコンストラクタは、クラス名と同じ名前を持ち、引数の数(または型)が互いに異なる必要があります。 実際にどのコンストラクタが呼び出されるかは、オ
-
C++のgetline関数の使い方を解説!文字列入力の基本とサンプルコード
C++のgetline関数は、ストリームから書式なし入力として文字を抽出し、C言語形式の文字列(C文字列)として指定した配列に格納するために使用されます。文字の抽出は、区切り文字が検出されるか、n文字(終端のNULL文字「\0」を含む)がsに書き込まれるまで続けられます。 宣言 basic_istream& getline (char_type* s, streamsize n); basic_istream& getline (char_type* s, streamsize n, char_type delim); パラメータ s:文字配列へのポインタです。抽出された文字
-
C++開発環境のセットアップガイド|エディタとコンパイラの準備方法
C++でプログラミングを始めるには、主に2つのソフトウェアが必要です。ソースコードを書くための「テキストエディタ」と、コードを実行可能なプログラムに変換する「C++コンパイラ」です。この記事では、それぞれの役割と、環境ごとのインストール手順をわかりやすく解説します。C++開発に必要な2つの基本ツールテキストエディタテキストエディタは、プログラムのソースコードを記述するためのツールです。代表的なものには、Windowsのメモ帳(Notepad)、OS標準のeditコマンド、Brief、Epsilon、EMACS、そしてvimやviなどがあります。エディタの名称やバージョンは、オペレーティングシス
-
【C++】STLで配列をシャッフルする方法:random_shuffleとshuffleの使い分けを解説
C++には、配列やコンテナの要素をランダムに並べ替えるための関数として、shuffleとrandom_shuffleが用意されています。これらの関数は配列だけでなく、vectorなどのコンテナにも同じ要領で使用できます。まずはrandom_shuffle()から見ていきましょう。 random_shuffle() 関数とは random_shuffle()は、指定した範囲 [left, right) 内の要素をランダムに並べ替える関数です。各要素の位置を、ランダムに選ばれた別の位置と交換することで、要素をシャッフルします。 さらに、独自の乱数生成関数を引数として渡すことで、「どの位置の要素を選
-
C++ STLのupper_bound()関数とは?使い方とサンプルコードを解説
この記事では、C++ STLにおけるupper_bound()関数について解説します。この関数は、コンテナ内で「valより後」とみなされる最初の要素を指すイテレータを返します。構文は以下の通りです。 iterator upper_bound (const value_type& val); const_iterator upper_bound (const value_type& val) const; 戻り値はイテレータであり、コンテナ内でvalより後とみなされる最初の要素を指します。なお、upper_bound()はlower_bound()と対になる関数で、lower_
-
C++で隣接要素のGCDが指定配列と一致する配列を構築する方法
問題の概要n個の要素を持つ配列A[]が与えられたとき、サイズがn+1である別の配列B[]を構築することを考えます。ここで要求される条件は、B[i]とB[i+1]の最大公約数(GCD)がA[i]と一致することです。条件を満たす解が複数存在する場合は、配列の要素の合計値が最小となるものを一つ出力します。例えば、A = [1, 2, 3] の場合、出力は [1, 2, 6, 3] となります。実際に確認すると、GCD(1, 2) = 1、GCD(2, 6) = 2、GCD(6, 3) = 3 となり、すべての条件を満たしています。アルゴリズムの考え方まず、Aに要素が1つだけある場合(その値をKとする
-
C++で同じインデックスの要素を除いた配列全体のXORから新しい配列を構築する方法
n個の正の整数で構成される配列A[]があるとします。このとき、B[i]が「A[i]以外のすべての要素のXOR」となるような別の配列Bを作成することを考えます。 例えば、A = [2, 1, 5, 9] の場合、結果は B = [13, 14, 10, 6] となります。 B[0] = 1 ^ 5 ^ 9 = 13 B[1] = 2 ^ 5 ^ 9 = 14 B[2] = 2 ^ 1 ^ 9 = 10 B[3] = 2 ^ 1 ^ 5 = 6 解法のアプローチ この問題を効率的に解く鍵となるのは、XORの重要な性質「a ^ a = 0(同じ値同士のXORは0になる)」です。手順は以下の通りで
-
C++でn個の要素の符号を反転して配列の合計を最大化する方法
問題の概要(2 × n − 1) 個の整数からなる配列が与えられます。この配列からちょうど n 個の要素を選び、それぞれの符号を反転(−1倍)することができます。この操作を行った結果として得られる配列の合計の最大値を求めるのが課題です。例入力配列が {-2, 100, -3} の場合を考えてみましょう。-2 と -3 の符号を反転すると、配列は {2, 100, 3} となり、合計は 105 になります。これがこの配列で達成できる最大の合計です。アルゴリズムこの問題は、以下の手順で効率的に解くことができます。配列内の負の数の個数を数えます。すべての要素の絶対値の合計を求めます。絶対値が最小とな