見出し画像

高校数学10分プログラミング(45日目、2024年8月2日)解説

本日の課題、おつかれさまでした。

自然数の中の特定の素因数の個数を数えるプログラムを作成することができたでしょうか。

解答例

1から150までの150個の自然数の積$${N=1 \cdot 2 \cdot \cdots \cdot 150}$$について$${N}$$を素因数分解したときの素因数3の個数を求めて、結果をコンソールに出力するプログラムの例は以下のようになります。

// 1から150までの150個の自然数N=1・2・…・150について
// Nを素因数分解したとき、素因数3の個数
void setup(){

  int N_max = 150; // Nの積の最大値
  int selected_prime_number = 3; // 選ばれた素因数 
 
  // N_max以下の素数を求める
  ArrayList<Integer> prime_numbers = getPrimeFactors(N_max);
  
  // 数値3が入っている位置
  int selected_index = prime_numbers.indexOf(selected_prime_number);
  
  // 1から150までをそれぞれ素因数分解して、素因数3の個数を数えていく
  int count = 0;
  ArrayList<Integer> exponents;
  for(int n=1; n<=N_max; n++){
    exponents = primefactorization(n, prime_numbers);
    count += exponents.get(selected_index);
  }
  
  println(count);
}

// 整数N以下の素数を求める関数
ArrayList<Integer> getPrimeFactors(
  int N // 2以上の整数
){
  // int型の可変配列を準備する
  ArrayList<Integer> prime_numbers = new ArrayList<Integer>();
  // 最初の素数2を可変配列に追加
  prime_numbers.add(2);
 
  boolean pn_flag; // 素数かどうかのフラグ
  // 3以上N以下の整数について素数であるかを確認する
  for(int n=3; n<=N; n++){
    pn_flag = true;
    for(int m=2; m<n; m++){
      if( n%m == 0 ){ // mで割り切れたらnは素数でない
        pn_flag = false;
      }
    }
    if(pn_flag){
      prime_numbers.add(n); // iが素数と判定された場合、可変配列に追加
    }
  }
  
  return prime_numbers;
}

// 素因数分解を行う関数
ArrayList<Integer> primefactorization(
  int N, // 2以上の整数
  ArrayList<Integer> prime_numbers // N以下の素数
){
  // 素因数分解したときの各冪に対する指数
  ArrayList<Integer> exponents = new ArrayList<Integer>();
  
  // 整数Nを素因数分解する
  boolean divisible_flag; // 割り切れたかどうかを判定するフラグ
  int quotient = N; // 素数で割ったときの商
  int pn; // 素数を代入する変数
  int exponent_count;
  for(int i=0; i<prime_numbers.size(); i++){
    pn = prime_numbers.get(i); // i番目の素数を取り出す
    divisible_flag = true;
    exponent_count = 0;
    while(divisible_flag){
      if( quotient % pn == 0 ){ // 商が素数pnで割り切れた場合
        exponent_count++; // pnに対する指数の値を1増やす
        quotient = quotient / pn; // 商を更新する
      } else { // 素数pnがNの素因数ではない、またはpnがNの素因数としてすべて算出された場合
        divisible_flag = false; 
      }
    }
    exponents.add(exponent_count);
  } 
  
  return exponents;
}

ソースコード2 1から150までの150個の自然数の積$${N=1 \cdot 2 \cdot \cdots \cdot 150}$$について$${N}$$を素因数分解したときの素因数3の個数を求めて、結果をコンソールに出力するプログラム(完成版)

Processing の開発環境ウィンドウを立ち上げて、そのテキストエディタ部分にソースコード2を書き写し、実行ボタン(左上の ▶ ボタン)を押すと、コンソールに、

72

と出力されます(図1)。

図1 コンソールに「72」と出力される

なお、今回の課題は、解析的に

$$
3\mathrm{の倍数の個数}(50) \\ +9\mathrm{の倍数の個数}(16) \\ +27\mathrm{の倍数の個数}(5) \\ +81\mathrm{の倍数の個数}(1) \\ = 72
$$

と計算することができますので、プログラム(ソースコード2)が正しい値を出力していることがわかります。

やってほしいこと

課題で説明した、
『1から150までの自然数を一つ一つ素因数分解してそれぞれの素因数3の個数を取り出してきてそれらの総和を求める』
の部分とプログラム(ソースコード2)の

  // 1から150までをそれぞれ素因数分解して、素因数3の個数を数えていく
  int count = 0;
  ArrayList<Integer> exponents;
  for(int n=1; n<=N_max; n++){
    exponents = primefactorization(n, prime_numbers);
    count += exponents.get(selected_index);
  }

の部分が対応していますので、今一度これらの対応関係を確認しておいてください。また、今回の課題について、記事『高校数学をプログラミングで解く(数学A編)「3-4 自然数の積と素因数の個数」』の自然数の中の特定の素因数の個数を数える問題の節でより詳しく説明していますので、そちらも見ておいてください。


今週は以上です。
来週も、整数の性質に関連したプログラムについて考えていきたいと思います。

来週もよろしくお願いします。

※今回の課題とその解答例について質問や疑問がある方は、本記事の下部にあるコメント欄からお願いします。

MK’s papa

この記事が気に入ったらサポートをしてみませんか?