C++で指定範囲内のユーナリー数をカウントする方法
2つの整数 start と end で表される範囲が与えられたとき、区間 [start, end] 内に存在する「ユーナリー数」の個数を求めるのが本記事の目的です。ユーナリー数とは、各桁の数字を2乗して合計する操作を繰り返したとき、最終的に 1 に到達できる数のことです(いわゆる「ハッピー数」と同じ性質を持つ数です)。
例として 13 という数を見てみましょう。
12 + 32 = 10
12 + 02 = 1
このように計算を繰り返して最終的な合計が 1 になるため、13 はユーナリー数です。
入力例と出力例
例1
入力:
start=1 end=20
出力:
範囲内のユーナリー数の個数:5
説明:
該当する数は次の通りです。
1, 7, 10, 12, 13
例2
入力:
start=50 end=100
出力:
範囲内のユーナリー数の個数:7
説明:
該当する数は次の通りです。
59, 63, 67, 74, 75, 78, 89
プログラムで使うアプローチ
1〜9 の中でユーナリー数となるのは 1 と 7 のみです。それ以外の数については、桁ごとの2乗和の計算を結果が 1 になるまで繰り返します。この処理を範囲内のすべての数に対して行い、ユーナリー数が見つかるたびにカウントを増やしていきます。
- 2つの整数 start と end を入力として受け取ります。
- 関数 check_unary(int number) は、渡された値がユーナリー数であれば true を、そうでなければ false を返します。
- 関数 Unary_range(int start, int end) は範囲を受け取り、その範囲内に含まれるユーナリー数の個数を返します。
- カウントを 0 で初期化し、for ループで i=start から end まで順に走査します。check_unary(i) が true を返すたびにカウントを1つ増やします。
- check_unary(int number) の内部では、合計値を保持する変数 total を用意します。
- number が 1 または 7 の場合は true を返します。それ以外の 10 未満の数(number / 10 == 0)の場合は false を返します。
- while ループの中で、各桁の数字を取り出して2乗し、total に加算していきます。
- 計算された合計値を引数として check_unary(int number) を再帰的に呼び出し、合計が 1 になるまで処理を続けます。
- 最終的にカウントを結果として返します。
コード例
#include <iostream>
using namespace std;
bool check_unary(int number){
int total = 0;
if (number == 1){
return true;
}
else if (number == 7){
return true;
}
else if (number / 10 == 0){
return false;
}
while (number != 0){
int temp = number % 10;
total += temp * temp;
number /= 10;
}
return check_unary(total);
}
int Unary_range(int start, int end){
int count = 0;
for (int i = start; i <= end; i++){
if (check_unary(i)){
count++;
}
}
return count;
}
int main(){
int start = 200, end = 400;
cout << "範囲内のユーナリー数の個数:" << Unary_range(start, end);
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
範囲内のユーナリー数の個数:31
この実装では、範囲内の各数について桁の2乗和の計算を繰り返すため、計算量はおおよそ O(範囲の幅 × 桁数) となります。なお、元のコードには合計値 total の初期化漏れと再帰呼び出し時の return 文の欠落という不具合がありましたが、上記のコードでは正しく動作するよう修正しています。
-
C++で平面内に形成できる平行四辺形の数を数えるアルゴリズム
本記事の課題は、平面上に与えられた点集合から形成できる平行四辺形の個数を求めることです。平行四辺形とは、四角形の対辺が互いに平行であり、それに伴って対角も等しくなる四角形のことを指します。 入力 − int a[] = {0, 2, 5, 5, 2, 5, 2, 5, 2} int b[] = {0, 0, 1, 4, 3, 8, 7, 11, 10} 出力 − 平面内の平行四辺形の数 − 3 説明 − (x, y) 座標の点が与えられており、これらの点を組み合わせると、図のように 3 つの平行四辺形を形成できます。 入力 − a[] = {0, 3, 1, 4, 1, 5} b[] =
-
C++で1からNまでの準素数(Almost Prime)の個数を求める方法
ある数 N が与えられたとき、1からNまでの範囲に含まれる「準素数(almost prime)」の個数を求める問題を考えてみましょう。準素数とは、異なる素因数をちょうど2つ持つ数のことです。素因数以外の約数(合成数の約数)はいくつあっても構いませんが、その中に含まれる素因数は正確に2種類である必要があります。例えば、Nが10の場合、出力は2になります。これは、条件を満たす数が 6(= 2 × 3)と 10(= 2 × 5)の2つしか存在しないためです。アプローチ:エラトステネスの篩を活用するこの問題を効率的に解くには、エラトステネスの篩(Sieve of Eratosthenes)を使って素数