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

C++でnCrが指定された素数で割り切れるかどうかを判定する方法

3つの変数 N、R、P があるとします。N と R から二項係数 NCR を求め、P は素数とします。このとき、NCR が P で割り切れるかどうかを判定するのが本記事の目的です。例えば、N = 7、R = 2、P = 3 の場合、7C2 = 21 となり、21 は 3 で割り切れるため、結果は true となります。

二項係数は一般的に次の式で表されます。

NCR = N! / (R! × (N − R)!)

ここでルジャンドルの定理(Legendre's Formula)を活用します。この定理を使うと、N!、R!、(N − R)! のそれぞれを割り切る素数 P の最大のべき乗(指数)を求めることができます。NCR が P で割り切れる条件は、N! に含まれる P の指数が、R! と (N − R)! に含まれる P の指数の合計よりも大きくなること、すなわち x(N!) > x(R!) + x((N − R)!) が成り立つことです。

アルゴリズムの仕組み

関数 getPower(n, p) は、ルジャンドルの定理に基づいて n! を割り切る素数 p の指数を計算します。具体的には、n を p で繰り返し割りながらその商を加算していくことで、⌊n/p⌋ + ⌊n/p²⌋ + ⌊n/p³⌋ + … を効率的に求めています。この値を N!、R!、(N − R)! のそれぞれに対して算出し、比較することで割り切れるかどうかを判定できます。

サンプルコード

#include <iostream>
using namespace std;
int getPower(int n, int p) {
   int pow = 0;
   while (n) {
      n /= p;
      pow += n;
   }
   return pow;
}
bool isDivisibleByP(int n, int r, int p) {
   // n!、r!、(n - r)! それぞれを割り切る
   // p の最大のべき乗を求める
   int x1 = getPower(n, p);
   int x2 = getPower(r, p);
   int x3 = getPower(n - r, p);
   if (x1 > x2 + x3)
   return true;
   return false;
}
int main() {
   int n = 7, r = 2, p = 7;
   if (isDivisibleByP(n, r, p))
      cout << "nCr is divisible by P";
   else
      cout << "nCr is not divisible by P";
}

実行結果

nCr is divisible by P

この例では N = 7、R = 2、P = 7 としています。7C2 = 21 は 7 で割り切れるため、プログラムは「nCr is divisible by P」と出力します。この方法を使えば、階乗の値を直接計算することなく大きな N に対してもオーバーフローを避けながら効率的に判定できます。


  1. C++でnに最も近いmの倍数を求めるアルゴリズムと実装方法

    問題の概要2つの整数 n と m が与えられたとき、「n に最も近く、かつ m で割り切れる数」を見つけることを考えます。候補が複数存在する場合は、絶対値が最大となる数を返します。また、n が m で完全に割り切れる場合は、そのまま n を返します。例えば、n = 13、m = 4 の場合、出力は 12 になります。13 に近い 4 の倍数としては 12 と 16 が候補ですが、13 との距離が近いのは 12 であるため、これが答えとなります。解決の手順この問題は、次のステップに従って解くことができます。まず q := n / m とし、n1 := m * q を計算しますn * m >

  2. 【C++】文字列内の「1(0+)1」パターンをすべて検出する方法

    文字列の中に「1(0+)1」という形式のパターンが含まれていると仮定します。ここで「(0+)」は、1個以上の「0」が連続して現れることを意味します。この記事では、文字列からこのパターンをすべて検出する方法を解説します。パターン同士が重なり合う場合もカウントの対象とします。なお、対象の文字列はバイナリ文字列であるとは限らず、数字と小文字の英字のみで構成された文字列を扱います。例として、文字列が「1101001」の場合を考えてみましょう。この場合、「101」と「1001」の2つのパターンが見つかります。解決のためのアプローチこの問題は、以下の手順に従って解くことができます。文字列内のすべての文字c