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

C++で級数 1+(1+2)+(1+2+3)+…+(1+2+3+…+n) の総和を求める方法

問題概要

この問題では、数値 n が与えられます。求めるのは、次の級数の総和です。

1 + (1+2) + (1+2+3) + (1+2+3+4) + … + (1+2+3+4+…+n)

入力例と出力例

入力:

n = 4

出力:

20

説明: (1) + (1+2) + (1+2+3) + (1+2+3+4) = 20

解法1: 二重ループを使う単純な方法

最もシンプルな解法は、外側のループで各項を順に生成し、内側のループでその項の値を計算して加算していく、二重ループを用いる方法です。

アルゴリズム

sum を 0 で初期化する
ステップ1: i を 1 から n までループする(i = 1 ~ n)
    ステップ1.1: j を 1 から i までループする(j = 1 ~ i)
        ステップ1.1.1: sum に j を加算する(sum += j)
ステップ2: sum を返す

実装例

この解法の動作を示すプログラムは以下の通りです。

#include <iostream>
using namespace std;

int calcSeriesSum(int n) {
    int sum = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
            sum += j;
    return sum;
}

int main() {
    int n = 7;
    cout << "級数 1 + (1+2) + (1+2+3) + ... + (1+2+3+...+" << n << ") の和は " << calcSeriesSum(n);
    return 0;
}

出力

級数 1 + (1+2) + (1+2+3) + ... + (1+2+3+...+7) の和は 84

しかし、このアプローチは時間計算量が O(n²) となるため、n が大きくなると処理に時間がかかり、あまり効率的とは言えません。

解法2: 数学的公式を使う効率的な方法

より効率的な解法は、級数の総和を表す一般公式を導出することです。各項は三角数 k(k+1)/2 で表せるため、これを利用して式を変形できます。

sum = 1 + (1+2) + (1+2+3) + (1+2+3+4) + …
sum = Σ ( k(k+1)/2 )
sum = ½ ( Σk² + Σk )
sum = ½ [ n(n+1)(2n+1)/6 + n(n+1)/2 ]
sum = ½ × n(n+1) × [ (2n+1)/6 + 1/2 ]
sum = ½ × n(n+1) × (2n+1+3)/6
sum = ½ × n(n+1)(2n+4)/6
sum = n(n+1)(2n+4)/12

この公式を使えば、ループ処理を行わずに O(1) の定数時間で答えを求められます。

実装例

この解法の動作を示すプログラムは以下の通りです。

#include <iostream>
using namespace std;

int calcSeriesSum(int n) {
    return (n * (n + 1) * (2 * n + 4)) / 12;
}

int main() {
    int n = 7;
    cout << "級数 1 + (1+2) + (1+2+3) + ... + (1+2+3+...+" << n << ") の和は " << calcSeriesSum(n);
    return 0;
}

出力

級数 1 + (1+2) + (1+2+3) + ... + (1+2+3+...+7) の和は 84

まとめ

二重ループによる解法は直感的で理解しやすいものの、O(n²) の計算量が必要になります。一方、数学的に導出した公式 n(n+1)(2n+4)/12 を使えば、O(1) で瞬時に結果を取得できます。競技プログラミングや大きな n を扱う場面では、公式を活用した解法が圧倒的に有利です。

  1. C++でarr[i]*iの合計を最大化する方法

    問題の概要N個の整数からなる配列が与えられます。配列の要素は自由に並べ替えることができます。そのうえで、Σarr[i] * i(i = 0, 1, 2, ... n-1)の最大値を求めるのが課題です。例えば、入力配列が {4, 1, 6, 2} の場合、要素を昇順に並べ替えることで最大値28が得られます。{1, 2, 4, 6} = (1 * 0) + (2 * 1) + (4 * 2) + (6 * 3) = 28アルゴリズムこの問題は、次の手順で解くことができます。配列を昇順にソートする配列を走査し、各要素にインデックスi(0, 1, 2, ..., n-1)を掛けて合計する合計値を返すな

  2. C++で等差数列(算術級数)の和を求めるプログラム

    初項「a」、公差「d」、項数「n」が与えられたとき、等差数列を生成し、その合計を計算するのが本プログラムの目的です。 等差数列(算術級数)とは 等差数列とは、隣り合う項の差が常に一定である数列のことです。数列の初項は「a」に固定され、項と項の間の共通の差(公差)は「d」で表されます。 数列は次のように表されます。 a, a + d, a + 2d, a + 3d, … 入力例と出力例 入力: a = 1.5, d = 0.5, n = 10 出力: 等差数列の合計は: 37.5 入力: a = 2.5, d = 1.5, n = 20 出力: 等差数列の合計は: 335 解き方のアプローチ