【C++】出席率75%を維持するために必要な最小講義数を求めるプログラム
はじめに
この問題では、これまでに開講された講義の総数を表す M と、学生がすでに出席した講義の回数を表す N の2つの数値が与えられます。求めるのは、C++で出席率75%を維持するために、今後最低限出席すべき講義の回数です。
問題の概要
大学生活において、出席率75%の維持は多くの学生にとって切実な関心事の一つです。本プログラムは、出席率75%を達成するために、学生が今後ために、学生が今後継続的に出席しなければならない講義の最小回数を計算します。
具体例を使って問題を確認してみましょう。
例1
入力: M = 32、N = 20
出力: 16
解説: 出席率75%以上を達成するには、最低でもあと16回の講義に出席する必要があります。これにより総講義数は48回、出席済み講義数は36回となります。
出席率 = 36 × 100 ÷ 48 = 75%
例2
入力: M = 14、N = 4
出力: 26
解説: 出席率75%以上を達成するには、最低でもあと26回の講義に出席する必要があります。これにより総講義数は40回、出席済み講義数は30回となります。
出席率 = 30 × 100 ÷ 40 = 75%
解法アプローチ①:シミュレーション(計算量 O(n))
求めたいのは、学生がこれから追加で出席すべき講義の回数です。最もシンプルな方法は、追加出席回数を1ずつ増やしながら出席率を計算し、その割合が75%以上になった時点でループを終了して、そのときの値を返すというものです。
この解法の動作を示すサンプルコード:
#include <iostream>
using namespace std;
int maintainAtt(int M, int N) {
int att = 0;
while(1){
if(((N+att)*100)/(M+att) >= 75){
return att;
}
att++;
}
}
int main() {
int M = 23, N = 12;
cout<<"The total number of lectures to be attended is "<<maintainAtt(M, N);
return 0;
}
実行結果
The total number of lectures to be attended is 21
※ 訳:「出席すべき講義の総数は21回です」
解法アプローチ②:数式を使った定数時間での求解(計算量 O(1))
上記の方法はループ処理を行うため、計算量は O(n) となります。しかし、必要な回数を数学的に導出すれば、O(1) の計算量で即座に答えを求めることが可能です。
条件「(N + att) ÷ (M + att) ≥ 0.75」を式変形すると、次のようになります。
N + att ≥ 0.75 × (M + att)
0.25 × att ≥ 0.75 × M − N
att ≥ (0.75 × M − N) ÷ 0.25
したがって、出席率75%を維持するために必要な最小講義数の公式は次のとおりです。
att = ⌈(0.75 × M − N) ÷ 0.25⌉(小数点以下は切り上げ)
この解法の動作を示すサンプルコード:
#include <iostream>
#include <math.h>
using namespace std;
int maintainAtt(int M, int N) {
int att = ceil(((0.75*M) - N)/(0.25));
return att;
}
int main() {
int M = 30, N = 11;
cout<<"The total number of lectures to be attended is "<<maintainAtt(M, N);
return 0;
}
実行結果
The total number of lectures to be attended is 46
※ 訳:「出席すべき講義の総数は46回です」
まとめ
出席率75%の維持という現実的な問題に対して、ループで1回ずつ試すシミュレーション方式でも十分に機能します。ただし、数式を用いた解法なら計算量 O(1) で一瞬にして答えを得られるため、入力値が大きい場合や高速な処理が求められる場面では、数式ベースのアプローチを採用するのが効果的です。
-
C++で対戦相手を捕まえるために必要な最小ラウンド数を求めるプログラム
問題の概要 木構造の辺のリストが [u, v] の形式で与えられるとします。これは頂点 u と頂点 v の間に無向辺が存在することを表しています。さらに、2つの整数 x と y も与えられます。自分は頂点 x におり、対戦相手は頂点 y に位置しています。ゲームは第1ラウンドに自分が移動し、次のラウンドで対戦相手が移動するという形で交互に進行します。対戦相手は、自分の番に移動せずその場にとどまることも選択できます。このとき、対戦相手を捕まえるために必要な最小ラウンド数を求めるのが課題です。 たとえば、入力が edges = [[0, 1], [0, 2], [1, 3], [1, 4]]、x
-
C++プログラムで数値の偶数の約数の合計を求める方法
このプログラムは、与えられた整数のすべての偶数の約数を見つけ、それらの合計を計算して画面に出力するものです。 実行例 入力 : 30 偶数の約数 : 2+6+10+30 = 48 出力 : 48 この問題を解くアプローチは、大きく分けて2つあります。 方法1:すべての約数を列挙して偶数のみを合計する まず対象の数値の約数をすべて求め、その中から偶数のものだけを取り出して合計します。この方法はシンプルで理解しやすい一方、約数を1つずつ確認するため、数値が大きくなると計算量が増えるという欠点があります。 方法2:素因数分解の公式を利用する より効率的なのが、素因数分解を利用した数学的な公式を使う方