C++でa[i]×a[j]の積が2の累乗になる非順序対(i, j)を数える方法
問題の概要
N個の要素からなる配列が与えられたとき、積が2の累乗(1, 2, 4, 8, 16, …)になるようなすべてのペア(Arr[i], Arr[j])の個数を求めます。ここで i ≠ j とします。つまり、Arr[i] × Arr[j] が2の累乗となるインデックスの組み合わせをカウントするのが目的です。
判定には対数を利用します。ある正の整数 prod が2の累乗であるかどうかは、log2(prod) が整数かどうかで確認できます。具体的には、ceil(log2(prod)) と floor(log2(prod)) が等しければ、prod は2の累乗であると判断できます。
入出力例
入力: Arr[] = { 4, 3, 2, 1, 2, 4 }、N = 6
出力: 積が2の累乗となるペアの数: 10
説明:
Arr[0]×Arr[2]=8、Arr[0]×Arr[3]=4、Arr[0]×Arr[4]=8、Arr[0]×Arr[5]=16
Arr[2]×Arr[3]=2、Arr[2]×Arr[4]=4、Arr[2]×Arr[5]=8
Arr[3]×Arr[4]=2、Arr[3]×Arr[5]=4、Arr[4]×Arr[5]=8
これら10組の積はすべて2の累乗です。
入力: Arr[] = { 3, 3, 3, 3, 3 }、N = 5
出力: 積が2の累乗となるペアの数: 0
説明: すべてのペアの積は9となり、2の累乗ではありません。
プログラムで使用するアプローチ
ランダムな値で初期化された整数型配列 Arr[] を用意します。
配列の長さを格納する変数 n を定義します。
関数 countPairs(int arr[], int n) は、配列とその長さを引数として受け取り、積が2の累乗となるペアの数を返します。
2重のforループで配列を走査し、各ペアを調べます。
外側のループは 0 ≤ i < n-1、内側のループは i < j < n の範囲で実行します。
arr[i] と arr[j] の積 prod を計算します。
ceil(log2(prod)) == floor(log2(prod)) が成り立つか確認します。成り立てば prod は2の累乗なので、カウントを1増やします。
すべてのループが終了した時点で、count には条件を満たすペアの総数が格納されています。
count を結果として返します。
なお、配列に0が含まれる場合、log2(0) は未定義となるため注意が必要です。実運用では prod > 0 のチェックを追加しておくと安全です。
C++実装例
#include <bits/stdc++.h>
#include <math.h>
using namespace std;
int countPairs(int arr[], int n){
int count=0;
int prod=0;
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
prod=arr[i]*arr[j];
if( ceil(log2(prod))==floor(log2(prod)) ){
count++;
//cout<<endl<<"a :"<<arr[i]<<" b :"<<arr[j]; //表示用
}
}
}
return count;
}
int main(){
int arr[] = { 2, 5, 8, 16, 128 };
int n = sizeof(arr) / sizeof(arr[0]);
cout <<endl<<"Pairs whose product is power of 2:"<<countPairs(arr, n);
return 0;
}
出力結果
上記のコードを実行すると、次の出力が得られます。
Pairs whose product is power of 2:6
配列 { 2, 5, 8, 16, 128 } の場合、積が2の累乗になるペアは以下の6組です。
- 2×8 = 16
- 2×16 = 32
- 2×128 = 256
- 8×16 = 128
- 8×128 = 1024
- 16×128 = 2048
-
C++でa²+b²=c²かつ1≦a≦b≦c≦nを満たすトリプレット(a、b、c)の個数を数える方法
問題概要整数 n が与えられます。この課題の目的は、以下の2つの条件を満たすトリプレット(3つの数の組み合わせ)を見つけ出し、その個数を求めることです。a2 + b2 = c21 ≦ a ≦ b ≦ c ≦ nこの問題は、1 ≦ a ≦ n および 1 ≦ b ≦ n の範囲で二重ループを実行することで解くことができます。各ループ内で c を計算し(c = sqrt(a² + b²))、両方の条件を満たす場合にカウントを増やしていきます。具体例を使って理解しましょう。入力 : N = 5出力 : トリプレットの個数 : 1説明 :a=3、b=4、c=5 のとき、両方の条件が満たされます。入力
-
C++で配列内の最大トリプレット合計を求める方法(i < j < k かつ a[i] < a[j] < a[k] の条件付き)
概要サイズ n の正整数からなる配列が与えられたとき、0 <= i < j < k < n かつ ai < aj < ak を満たすトリプレット(ai + aj + ak)の中で最大の合計値を求めるのが本記事の課題です。入力例a[] = 3 6 4 2 5 10出力例19説明考えられるすべてのトリプレットは以下の通りです。 3 4 5 => 合計 = 12 3 6 10 => 合計 = 19 3 4 10 => 合計 = 17 4 5 10 => 合計 = 19 2 5 10 => 合計 = 17 最大合計 = 19解法アプロー