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

C++で積がN未満となる順序対の個数をカウントする方法

問題概要

整数 N が与えられたとき、2つの正の整数からなる順序対(ペア)のうち、その積がN未満になるものをすべて数え上げることを目標とします。

この問題は、i を 1 から N 未満まで、j を 1 から i*j < N を満たす範囲まで動かしながら、条件を満たす組み合わせの数をカウントしていくことで解けます。

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

入力例 1

N=4

出力例 1

Ordered pairs such that product is less than N: 5

説明

Pairs will be (1,1) (1,2) (1,3) (2,1) (3,1)

積が4未満となる順序対は (1,1)、(1,2)、(1,3)、(2,1)、(3,1) の5つです。順序対であるため、(1,2) と (2,1) は異なるペアとして別々にカウントされる点に注意してください。

入力例 2

N=100

出力例 2

Ordered pairs such that product is less than N: 473

説明

Pairs will be (1,1) (1,2) (1,3)....(97,1), (98,1), (99,1). Total 473.

アルゴリズムのアプローチ

  • 整数 N を入力として受け取ります。
  • 関数 productN(int n) は引数 n を受け取り、積が n 未満となる順序対の個数を返します。
  • ペアの個数を保持する変数 count を 0 で初期化します。
  • 2重の for ループを使ってペアを生成していきます。
  • 外側のループは i = 1 から i < n まで、内側のループは j = 1 から (i * j) < n を満たす間だけ回します。
  • 条件を満たすたびに count を 1 ずつ増加させます。
  • すべてのループが完了した時点で、count には該当する順序対の総数が格納されています。
  • count を結果として返します。

C++実装例

#include <bits/stdc++.h>
using namespace std;
int productN(int n){
    int count = 0;
    for (int i = 1; i < n; i++){
        for(int j = 1; (i*j) < n; j++)
            { count++; }
    }
    return count;
}
int main(){
    int N = 6;
    cout <<"Ordered pairs such that product is less than N:"<<productN(N);
    return 0;
}

出力

上記のコードを実行すると、以下の出力が得られます。

Ordered pairs such that product is less than N:10

計算量について

外側のループは最大 N−1 回、内側のループは各 i に対して最大 ⌊(N−1)/i⌋ 回実行されるため、この実装の時間計算量は O(N log N) 程度となります。

また、求めたい個数は数学的には Σ⌊(N−1)/i⌋(i = 1 〜 N−1)として表せます。これは「xy ≤ m となる格子点の個数」を数える問題と同じであり、区間ごとにまとめて計算するブロック分割(ハイパボラ法)などのテクニックを用いれば、O(√N) まで高速化することも可能です。大きな N を扱う場合は、こうした最適化を検討するとよいでしょう。

  1. 【C++】aの個数がbより多い部分文字列の総数を効率的に求める方法

    この問題では、文字 a と b のみで構成された文字列 str と整数 N が与えられます。str を N 回繰り返して連結することで新しい文字列を作成し、その中に含まれる「a の出現回数が b より多い」部分文字列の総数を求めて出力するのが課題です。 問題の例 まず、具体的な例で問題を確認してみましょう。 入力: aab 2 出力: 9 説明: 作成された文字列は aabaab。 条件を満たす部分文字列: a, aa, aab, aaba, aabaa, aabaab, aba, baa, abaa 解法のアプローチ この問題を解くには、毎回完全な文字列を生成するのではなく、元の文字列 st

  2. C++でY以下となる数値集合の最小個数を求めるアルゴリズム

    問題の概要連続した数字からなる文字列と数値 Y が与えられます。このとき、以下のルールをすべて満たす集合の最小個数を求めるのが課題です。各集合は、元の文字列から連続して取り出した数字で構成すること同じ桁(文字)を複数回使用してはならない集合内の数値は Y を超えてはならない入力例と出力例たとえば、str = 1234、Y = 20 とすると、次のように 3 つの集合に分割できるため、答えは 3 になります。{12}, {3}, {4}{12} は 20 以下であり、{3} と {4} もそれぞれ 20 以下です。すべての数字が一度ずつ使われていることも確認できます。アルゴリズムこの問題は貪欲法