C++で川の流速と上り・下りの時間比から人の速さを求める方法
この問題では、川の流速 S(km/h)と、上り(上流方向)と下り(下流方向)の移動時間の比率 N の2つの値が与えられます。求めるのは、これらの情報から静水中における人の速さです。
具体例で問題を確認してみましょう。
入力
S = 5, N = 2
出力
15
これは、流速が 5 km/h で、同じ距離を上るときと下るときの所要時間の比率が 2 : 1 の場合、静水中の速さが 15 km/h になることを意味します。
解法アプローチ
この問題は、流水問題(ボートと川の流れの問題)でよく使われる数学的な公式を利用することで、シンプルに解くことができます。ここからは、その公式がどのように導かれるのかを順番に見ていきましょう。
静水中の人の速さ = x km/h 川の流速 = S km/h 下り(流れと同じ向き)の速さ = (x + S) km/h 上り(流れに逆らう向き)の速さ = (x − S) km/h ある距離を下るのにかかる時間 = T 同じ距離を上るのにかかる時間 = n × T 下りの移動距離 = (x + S) × T 上りの移動距離 = (x − S) × n × T
下りと上りで移動する距離は同じであるため、次の等式が成立します。
(x + S) × T = (x − S) × n × T x + S = nx − nS S + nS = nx − x S × (n + 1) = x × (n − 1)
これを x について整理すると、次の公式が得られます。
$$x=\frac{S \times (n+1)}{(n-1)}$$
この公式を使えば、流速と時間の比率だけで静水中の速さを簡単に計算できます。
それでは、この解法の動作を示すプログラムを見てみましょう。
実装例
#include <iostream>
using namespace std;
float calcManSpeed(float S, int n) {
return ( S * (n + 1) / (n - 1) );
}
int main() {
float S = 12;
int n = 3;
cout<<"人の速さは "<<calcManSpeed(S, n)<<" km/h です";
return 0;
}
出力
人の速さは 24 km/h です
計算の検証
S = 12、n = 3 を公式に代入すると、12 × (3 + 1) ÷ (3 − 1) = 12 × 4 ÷ 2 = 24 km/h となり、正しく計算できていることが確認できます。
-
O(n)時間・O(1)の追加メモリで重複要素を検出する方法 - C++実装(その1)
0からn-1までの範囲の数値が格納されたリストがあるとします。同じ数値は何度でも繰り返し出現する可能性があります。ここで求めたいのは、追加のメモリを使用せずに、繰り返し現れる数値をすべて検出することです。 例として、リストが [5, 2, 3, 5, 1, 6, 2, 3, 4, 1] の場合を考えてみましょう。このとき答えは 5, 2, 3, 1 となります。 解法のアプローチ この問題を解くには、リスト内の各要素 e に対して、以下の手順を実行します。 sign := A[e の絶対値] を確認する sign が正の値であれば、その値を負に変更する すでに負の値であれば、その数値は重複し
-
C++でGCDとLCMの値から条件を満たす数のペアの総数を求める方法
この記事では、最大公約数(GCD)と最小公倍数(LCM)の値が与えられたとき、その両方の条件を満たす整数のペアが全部で何通り存在するかを求める方法を解説します。 例として、GCDが2、LCMが12の場合を考えてみましょう。この条件を満たすペアは (2, 12)、(4, 6)、(6, 4)、(12, 2) の4つです。プログラムの目的は、このペアの総数「4」を計算することです。 解決の鍵となる数学的性質 2つの整数 a と b の間には、次のような重要な関係が常に成り立ちます。 a × b = GCD(a, b) × LCM(a, b) また、a と b はいずれも必ず GCD で割り切れるた