C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】arr[i] = i×(-1)^i となる配列で、インデックスLからRまでの要素の総和を求める方法

問題概要

この問題では、2つの整数 LR が与えられます。また、arr[i] = i × (-1)i として定義される配列 arr[] を考えます。求めたいのは、この配列におけるインデックス L から R までの要素の総和です。

arr[i] は、インデックスが偶数のとき正の値、奇数のとき負の値になります。そのため、範囲 [L, R] 内の要素に対して「偶数インデックスは加算、奇数インデックスは減算」という処理を行った結果が答えとなります。

問題を理解するための具体例

入力:

L = 2 , R = 6

出力:

4

説明:

arr[] = {-1, 2, -3, 4, -5, 6}
Sum = 2 + (-3) + 4 + (-5) + 6 = 4

解法1:素朴なアプローチ(ループで計算)

最もシンプルな解決策は、L から R までループを回し、偶数インデックスの要素をすべて加算し、奇数インデックスの要素をすべて減算していく方法です。最後に合計値を返します。

実装例

#include <iostream>
#include <math.h>
using namespace std;

int CalcArrSumLtoR(int L, int R) {
    int sum = 0;
    for (int i = L; i <= R; i++){
        sum += (i * pow((-1), i));
    }
    return sum;
}

int main() {
    int L = 3, R = 15;
    cout<<"Sum of elements of array from index "<<L<<" to "<<R<<" is "<<CalcArrSumLtoR(L, R);
    return 0;
}

出力

Sum of elements of array from index 3 to 15 is -9

このアプローチは直感的で分かりやすいですが、範囲内の全要素を順番に走査する必要があるため、時間計算量は O(n) となり、必ずしも効率的とはいえません。

解法2:数式を活用した効率的なアプローチ

より効率的な解決策は、奇数および偶数の和に関する数学的公式を利用することです。

  • 最初の n 個の奇数の和 = n × n
  • 最初の n 個の偶数の和 = n × (n + 1)

これらの公式を用いると、最終的な合計は次のように計算できます。

sum =(最初のR個の偶数の和 − 最初の(L-1)個の偶数の和)−(最初のR個の奇数の和 − 最初の(L-1)個の奇数の和)

ここで重要なのは、n までの間には偶数と奇数がそれぞれ約 n/2 個ずつ存在するという点です。つまり、R 以下には R/2 個の偶数があるため、R/2 や L/2 の値を使って各区間の和を求めます。この方法なら、配列を走査せずに定数時間 O(1) で答えを得られます。

実装例

#include <iostream>
using namespace std;

long int findSum(int n, bool isEven) {
    long int total = 0;
    if(isEven == true){
        total = (n) / 2;
        return (total * (total+1));
    }
    else {
        total = (n + 1) / 2;
        return total * total;
    }
}

int CalcArrSumLtoR(int L, int R) {
    return (findSum(R, true) - findSum(L - 1, true)) - (findSum(R, false) - findSum(L - 1, false));
}

int main() {
    int L = 3, R = 15;
    cout<<"Sum of elements of array from index "<<L<<" to "<<R<<" is "<<CalcArrSumLtoR(L, R);
    return 0;
}

出力

Sum of elements of array from index 3 to 15 is -9

まとめ

本記事では、arr[i] = i × (-1)i で定義される配列の区間 [L, R] の総和を求める問題について、O(n) のループによる素朴な解法と、奇数・偶数の和の公式を活用した O(1) の効率的な解法の2つを紹介しました。数学的な性質を利用して計算量を大幅に削減できるのは、アルゴリズム設計の好例といえるでしょう。

  1. C++で暗号化配列(他の要素の合計からなる配列)から元の配列を復元する方法

    整数の配列が与えられ、この配列が「暗号化された配列」であるとします。例えば、暗号化配列が A = [10, 14, 12, 13, 11] で、元の配列が B = [5, 1, 3, 2, 4] だったとしましょう。このとき、配列 A の各要素 A[i] は次の規則に従っています。A[i] = 元の配列 B における、自分自身(B[i])を除くすべての要素の合計この記事では、このような暗号化された配列から、元の配列を効率的に復元する方法を解説します。解法の考え方:算術的な観察この問題は、シンプルな算術的な性質に基づいて解くことができます。まず、配列のサイズを 4 と仮定し、元の配列を B =

  2. C++で配列の全要素にXOR演算を適用して合計を最小化する方法

    問題の説明サイズNの配列が与えられます。配列の各要素とある整数XとのXOR演算を行ったとき、その結果の合計が最小となるようなXを見つけてください。例として、入力配列が arr[] = {8, 5, 7, 6, 9} の場合、最小合計は 30 になります。各配列要素の2進数表現は次のとおりです。8 : 1000 5 : 0101 7 : 0111 6 : 0110 9 : 1001X = 5 のとき、XOR演算後の各値と合計は以下のようになります。8 ^ 5 = 13 5 ^ 5 = 0 7 ^ 5 = 2 6 ^ 5 = 3 9 ^ 5 = 12 合計 = 30(13 + 0 + 2 + 3