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

C++で指定された範囲内の x² ≡ 1 (mod p) の解の個数を数える方法


問題の概要

整数 np が与えられたとき、合同式 x2 ≡ 1 (mod p) を満たす x のうち、x が範囲 [1, N] に含まれるものがいくつあるかを求めるのがこの記事の目的です。

最も基本的なアプローチは、1 から N までの各整数を順番に x として調べ、「(x × x) % p == 1」が成立するかどうかを判定し、条件を満たすたびにカウントを 1 増やしていくというものです。

それでは、具体的な例を使って理解していきましょう。

入力例 1

  • 入力:n = 5、p = 2

  • 出力:解の個数 = 3

  • 説明:範囲 1〜5 の間で各値を確認します。

12 = 1 % 2 = 1 → count = 1
22 = 4 % 2 = 0 → count = 1
32 = 9 % 2 = 1 → count = 2
42 = 16 % 2 = 0 → count = 2
52 = 25 % 2 = 1 → count = 3
解の総数 = 3

入力例 2

  • 入力:n = 3、p = 4

  • 出力:解の個数 = 2

  • 説明:範囲 1〜3 の間で各値を確認します。

12 = 1 % 4 = 1 → count = 1
22 = 4 % 4 = 0 → count = 1
32 = 9 % 4 = 1 → count = 2
解の総数 = 2

アルゴリズムの考え方

このプログラムでは、以下の手順を採用しています。

  • 2 つの変数 n と p を受け取ります。

  • 関数 solutionsCount(int n, int p) は引数 n と p を受け取り、合同式 x2 ≡ 1 (mod p) の解の個数を返します。

  • x = 1 から x = n まで順にループし、(x * x) % p == 1 が成立する場合はカウントを 1 増やします。

  • ループが終了した時点で、count には解の総数が格納されています。

  • count を結果として返します。

C++ 実装例

#include<bits/stdc++.h>
using namespace std;
int solutionsCount(int n, int p){
    int count = 0;
    for (int x=1; x<=n; x++){
        if ((x*x)%p == 1)
            { ++count; }
    }
    return count;
}
int main(){
    int n = 8, p = 3;
    cout<<"Number of solutions :"<<solutionsCount(n, p);
    return 0;
}

実行結果

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

Number of solutions : 6

補足:計算量と注意点

この手法の時間計算量は O(N) であり、N が大きくなるほど処理に時間がかかる点に注意が必要です。また、n や p が大きい場合には x * x の計算結果が int 型の上限を超えてオーバーフローする恐れがあるため、必要に応じて long long 型を使うと安全です。さらに、p が奇素数である場合、合同式 x2 ≡ 1 (mod p) の解は mod p の世界では +1 と −1 の 2 つに限られるという数学的性質があるため、これを活用すればより効率的な解法を構築することも可能です。

  1. C++で16進数の英字(A〜F)を数える方法

    開始値と終了値を持つ範囲が与えられ、その範囲内に存在する16進数の英字(A〜F)の個数を計算するのが本記事の課題です。 16進数の英字とは? コンピュータの分野において、16進数とは基数が16である数値体系のことです。これは、2進数のデータを16進数の1桁でコンパクトに表現できることを意味します。16進数は0から15までの整数で構成されており、10は「A」、11は「B」、12は「C」、13は「D」、14は「E」、そして15は「F」という英字で表されます。 そのため、以下のプログラムでは、指定された範囲内に16進数の英字(A〜F)がいくつ含まれているかを判定・集計します。 具体例 入力 − st

  2. C++で指定された範囲内の階乗数の個数を数える方法

    整数値が格納された変数startから変数endまでの範囲が与えられ、その範囲内に存在する階乗数の総数を求めるのがこの課題です。 階乗数とは ある数の階乗とは、その数から1ずつ減らしながら順に掛け合わせて計算される値です。「!」という記号で表され、0!、1!、2!、3!、5!のように書きます。なお、0!と1!はどちらも常に1となります。 例:2の階乗 = 2 × (2−1) = 2 × 1 = 2   3の階乗 = 3 × (3−1) × (2−1) = 3 × 2 × 1 = 6 具体例 入力 − start = 5, end = 600 出力 − 階乗数の個数は 3 説明 − 5〜60