C++で特定の増殖率におけるn秒後のa・b・cの個数を求める方法
3つの数値「a」「b」「c」を入力として与え、n秒後のそれぞれの個数を求めるのがこの問題のゴールです。増殖(変化)のルールは以下のとおりです。
- 各aは2秒ごとにbへ変化する
- 各bは5秒ごとにcへ変化する
- 各cは12秒ごとに2つのaへ変化する
例を使って理解しよう
例1
入力 − n_seconds = 62、a = 1、b = 1、c = 1
出力 −
指定された増殖率におけるn秒後のaの個数:0
指定された増殖率におけるn秒後のbの個数:33
指定された増殖率におけるn秒後のcの個数:1
説明 − 60秒経過した時点で、aは32、bは0、cは0になります。
さらに2秒経過すると、すべてのaがbへ変化してb=33となり、cはそのまま1が残ります。
例2
入力 − n_seconds = 20、a = 1、b = 1、c = 1
出力 −
指定された増殖率におけるn秒後のaの個数:0
指定された増殖率におけるn秒後のbの個数:0
指定された増殖率におけるn秒後のcの個数:6
説明
1秒後 : a=1、b=1、c=1
2秒後 : a=0、b=2(1+1)、c=1 → 2秒経過でaがbへ変化
4秒後 : a=0、b=2、c=1 → 変化なし
5秒後 : a=0、b=0、c=3(1+2) → 5秒経過でbがcへ変化
6〜10秒後 : a=0、b=0、c=3 → 変化なし
12秒後 : a=6(0+2×3)、b=0、c=0 → 12秒経過でcが2つのaへ変化
14秒後 : a=0、b=6(0+6)、c=0 → 2秒経過でaがbへ変化
15秒後 : a=0、b=0、c=6(0+6) → 5秒経過でbがcへ変化
16〜20秒後 : a=0、b=0、c=6 → 変化なし
プログラムで使うアプローチ
2、5、12の最小公倍数(LCM)は60秒です。したがって、60秒ごとのa・b・cの変化は次のようになります。
60秒 → a=32、b=0、c=0
120秒 → a=32×32、b=0、c=0
180秒 → a=32×32×32、b=0、c=0
n_secondsが60の倍数の場合は、上記の規則からaの個数を直接計算できます。そうでない場合は、n_seconds以下で最大の60の倍数をtempとして求め、temp+1秒から入力された秒数まで1秒ずつ走査しながら、剰余(2、5、12)を使って変化を計算していきます。
- 数値a、b、cを入力として受け取る。
- 時間(秒)を表すn_secondsを受け取る。
- 関数reproduction_rate(int n_seconds, int a, int b, int c)がすべての引数を受け取り、指定された増殖率におけるn秒後のa・b・cの個数を出力する。
- temp = n_seconds / 60 として、n_secondsに含まれる60の倍数の個数を求める。
- a = (int)pow(32, temp) を計算する(すなわち32temp)。
- temp = 60 × temp として、n_seconds以下で最大の60の倍数に更新する。
- forループで i = temp+1 から i = n_seconds まで走査する。
- iが2の倍数なら、bにaを加算し、aを0にする。
- iが5の倍数なら、cにbを加算し、bを0にする。
- iが12の倍数なら、aに2×cを加算し、cを0にする。
- forループ終了後、a・b・cの最終的な値を出力する。
コード例
#include <bits/stdc++.h>
using namespace std;
void reproduction_rate(int n_seconds, int a, int b, int c) {
int temp = n_seconds / 60;
a = (int) pow(32, temp);
temp = 60 * temp;
for (int i = temp + 1; i <= n_seconds; i++) {
if (i % 2 == 0) {
b = b + a;
a = 0;
}
if (i % 5 == 0) {
c = c + b;
b = 0;
}
if (i % 12 == 0) {
a = a + (2 * c);
c = 0;
}
}
cout << "指定された増殖率におけるn秒後のaの個数: " << a << "\n";
cout << "指定された増殖率におけるn秒後のbの個数: " << b << "\n";
cout << "指定された増殖率におけるn秒後のcの個数: " << c;
}
int main() {
int n_seconds = 72;
int a = 2;
int b = 1;
int c = 1;
reproduction_rate(n_seconds, a, b, c);
return 0;
}
上記のコードを実行すると、次の出力が得られます。
出力
指定された増殖率におけるn秒後のaの個数: 68 指定された増殖率におけるn秒後のbの個数: 0 指定された増殖率におけるn秒後のcの個数: 0
-
C++で円をN回カットしたときのピース数を計算する方法
問題の概要整数Nが与えられます。このNは、2次元平面上の円に対して加える「カット(切り込み)」の回数を表します。1回のカットによって円は2つに分けられるため、N回のカットを行った後に円がいくつのピースに分割されるかを求めるのが、この問題の目的です。計算式この問題はとてもシンプルで、次の式で答えを求めることができます。ピースの数 = 2 × カットの回数(N)各カットが円の中心を通って切断されると考えると、カット1回ごとにピースが2つずつ増えていくため、この式が成り立ちます。具体例入力: N = 1出力: 円のピース数: 2説明: 1回のカットで、円はちょうど2つの半分に分けられます。入力: N
-
C++で解説:T秒後のカエルの位置を求める確率計算アルゴリズム
n個の頂点からなる無向木(ツリー)があるとします。頂点には1からnまでの番号が付けられており、カエルは頂点1からジャンプを開始します。カエルは、現在いる頂点に隣接している「未訪問」の頂点へ、1秒でジャンプすることができますが、一度訪れた頂点へ戻ることはできません。ジャンプ先の候補が複数ある場合は、いずれも等しい確率でランダムに1つを選んで移動します。逆に、行ける未訪問の頂点がなくなったカエルは、その場で永遠に跳ね続けることになります。 木は辺の配列として与えられます。ここで求めたいのは、「t秒後にカエルが頂点targetの上にいる確率」です。 問題の例 たとえば、入力が n = 7、t = 2