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

C++で合計が素数になる部分配列を数える方法

正の整数からなる配列が与えられたとき、要素の合計が素数になる部分配列(サブ配列)の個数を求めるのが本記事の目的です。例えば、配列 {1, 2, 3, 4} の場合、隣接する要素からなる部分配列 {1,2}、{2,3}、{3,4} の合計はそれぞれ 3・5・7 となり、いずれも素数であるため、条件を満たす部分配列は 3 個となります。

具体的な例で確認してみましょう。

入力 − arr[] = {1, 3, 5, 3, 2}

出力 − 合計が素数になる部分配列の数: 3

説明 − 該当する部分配列は {3, 2}(合計 5)、{3, 5, 3}(合計 11)、{3, 5, 3, 2}(合計 13)の 3 つで、いずれも素数です。

入力 − arr[] = {2, 4, 6}

出力 − 合計が素数になる部分配列の数: 0

説明 − すべての部分配列の合計が素数ではありません。例えば {2, 4} の合計は 6、{4, 6} の合計は 10 です。

プログラムで使用するアプローチ

まず、エラトステネスの篩(ふるい)を用いて最大値 107 までのすべての素数を事前に求め、vector<bool> 型の check に格納します。数 i が素数であれば check[i] は true、そうでなければ false となります。その後、二重の for ループで配列を走査し、部分配列の合計を累積しながら check[sum] を参照して素数かどうかを判定します。素数であればカウントを 1 つ増やします。

  • 正の整数からなる配列 arr[] を受け取ります。

  • 関数 sub_prime(int arr[], int size) は配列を受け取り、合計が素数になる部分配列の個数を返します。

  • カウントの初期値を 0 とします。

  • temp = pow(10, 7) を最大値として初期化します。

  • vector check を true で初期化します。

  • check[0] と check[1] は素数ではないため false に設定します。

  • i = 2 から i * i <= temp の間、各 i についてその倍数をすべて false(非素数)としてマークします。

  • これにより、check[i] は i が素数のとき true、それ以外は false となります。

  • 続いて、二重の for ループで再び配列を走査します。

  • 変数 total を部分配列 arr[i] 〜 arr[j] の合計として管理します(i は 0 〜 size-2、j は i+1 〜 size-1)。

  • check[total] が true であれば(total が素数であれば)カウントを増やします。

  • すべてのループが終わった時点で count を結果として返します。

コード例

#include <bits/stdc++.h>
using namespace std;
int sub_prime(int arr[], int size){
    int count = 0;
    int temp = int(pow(10, 7));
    vector<bool> check(temp + 1, true);
    check[0] = false;
    check[1] = false;
    for (int i = 2; i * i <= temp; i++){
        if (check[i] == true){
            for (int j = i * 2; j <= temp; j += i){
                check[j] = false;
            }
        }
    }
    for (int i = 0; i < size - 1; ++i){
        int total = arr[i];
        for (int j = i + 1; j < size; ++j){
            total += arr[j];
            if (check[total]){
                ++count;
            }
        }
    }
    return count;
}
int main(){
    int arr[] = { 3, 5, 1, 9, 5 };
    int size = sizeof(arr) / sizeof(arr[0]);
    cout<<"合計が素数になる部分配列の数: "<<sub_prime(arr, size);
    return 0;
}

出力

上記のコードを実行すると、次のような出力が得られます −

合計が素数になる部分配列の数: 1
  1. C++で合計が0となるすべての部分配列を出力する方法

    この記事では、整数値の配列が与えられたときに、要素の合計が0になるすべての部分配列(連続した要素の並び)を見つけ出し、それらを出力する方法をC++で解説します。 問題の概要 まず、具体例を使って問題を理解しましょう。 入力: arr[] = {-5, 0, 2, 3, -3, 4, -1} この配列の場合、合計が0になる部分配列は以下の通りです。 {0} … インデックス1のみ {-5, 0, 2, 3} … インデックス0〜3 {3, -3} … インデックス3〜4 {-3, 4, -1} … インデックス4〜6 {-5, 0, 2, 3, -3, 4, -1} … インデックス0〜6(配

  2. C++でサイズKの重複しないM個の部分配列の最大合計を求める方法

    問題文配列と2つの数値 M・K が与えられます。このとき、配列の中からサイズ K の重複しない部分配列を選び、そのうち最大 M 個の合計値を求めることが課題です(配列の要素の順序は変更されません)。ここで、K は部分配列のサイズ、M は選ぶ部分配列の個数を表します。配列のサイズは m × k より大きいものと仮定して構いません。また、配列全体のサイズが k の倍数でない場合は、末尾の部分配列を部分的に採用することも可能です。入力例たとえば、配列が {2, 10, 7, 18, 5, 33, 0}、N = 7、M = 3、K = 1 である場合を考えます。このとき選択される部分集合は次の通りです