juten10x

Info - Blog - Gallerypile_of_codes (study/3) > Problems_forschool*1

Problems_forschool*1

目次

count_divisors

問題

$100$ の正の約数の個数を求めてください.

出力

ブラウザに答えを出力してください.

解説

開く

for文で $i=1, \ldots, 100$ まで回しましょう.そして,各 $i$ について $100$ を $i$ で割った余りを計算し,余りが $0$ になる場合にカウント用の変数を $1$ 増やしていくと, $100$ の正の約数の個数を求めることができます.

よって答えは9であると求めることができます.

JavaScriptによる解答例を以下に示します.


let cnt = 0;

for (let i = 1; i <= 100; i++) {
  if (100 % i == 0) cnt += 1;
}

document.write(cnt);

別解(素因数分解する)

ここから先は少し難しい内容のため,読み飛ばしていただいても構いません. (また,この方針では,可読性を低下させずにコードを書くと10行を超えてしまいます.ただ,想定解は可読性を確保した上で全て10行以内で書けるようにしていますので,これはあくまでも別解として捉えてください.)

素因数分解して,正の約数の個数を求めましょう.まず, $100$ を素因数分解すると $100=2^2\cdot5^2$ ですね.ここで, $100=2^a\cdot5^b\ (a=0,1,2,\ b=0,1,2)$ とすると, $100$ の全ての約数を表すことができます. $a$ の値と $b$ の値の組み合わせを考えると,それぞれ $3$ つの値をとるため, $3\times3=9$ により, $9$ 通り.つまり, $9$ 個の正の約数をもつことがわかります.では、以上のことをプログラムで実装してみましょう.

まず,いま求めたいのは $100$ を素因数分解した式そのものではなく, $100$ を素因数分解した式における指数の積です.ゆえに,宣言する変数はカウント用の変数(ここでは $cnt$ とします),答えを保持する変数(ここでは $ans$ )に $1$ を代入したもの, $100$ を代入した変数(ここでは $N$ )のみでよいです.次に,for文で $i=2$ に $1$ ずつ加算していき,それぞれの $i$ で $N$ を割れるだけ割ります.その際に, $cnt$ に $N$ は $i$ で何回割れるかを記録していきます.ここで, $cnt$ は $100$ を素因数分解した式における, $i$ の指数を表しています.よって,その処理の後に同じfor文中で毎度 $ans$ に $cnt+1$ を乗算すれば,for文の処理が終わった際には $ans$ の値は $100$ の正の約数の個数となっているはずです.また、このように処理を繰り返していくと $N$ はいずれ $1$ になるため, $N\ne1$ をfor文内の処理が実行される条件とすればよいです.(なお, $N$ を $i$ で一度も割れない場合には $cnt$ の値は $0$ ですが, $ans$ に乗算する際には $cnt(=0)+1=1$ となるため,結局 $1$ をかけることになり, $ans$ の値は変わりません.したがって,その点については場合分けしなくてもよいです.)

以上により,JavaScriptで以下のように書くことができます.


let cnt = 0, ans = 1, N = 100;

for (let i = 2; N != 1; i++) {
  cnt = 0;
  while (N%i == 0) {
    N /= i;
    cnt += 1;
  }
  ans *= (cnt + 1);
}

document.write(ans);

out_a

問題

初項 $1$ ,公差 $2$ の等差数列を $a$ とします.数列 $a$ の初項から第 $10$ 項までを求め,以下の出力形式に従って出力してください.

出力

ブラウザに $a_1, a_2, \ldots, a_{10}$ を,空白区切りで出力してください.

解説

開く

解法 $1$ : そのまま実装する

問題文にそって,そのまま書いてみましょう. まず,要素数 $10$ の配列を用意します.それぞれの要素について,とりあえず $0$ などで初期化しておきましょう. 次に,for文を $i=0, \ldots, 9$ まで回し,配列のそれぞれの要素について,一般項からその項にあたる値を求め,代入します.そして最後に,for文を用いて出力しましょう.ここで,各項の間に空白を入れるには,毎度出力したあとに同じfor文のなかで $i<9$ が真である場合に空白を出力すればよいでしょう.

よって答えは1 3 5 7 9 11 13 15 17 19になります.

JavaScriptによる解答例を以下に示します.


let a = [0,0,0,0,0,0,0,0,0,0];

for (let i = 0; i < 10; i++) {
  a[i] = 1 + i*2
}

for (let i = 0; i < 10; i++) {
  document.write(a[i]);
  if (i < 9) document.write(" ");
}

解法 $2$ : 工夫して実装する

工夫して書いてみましょう. 解法 $1$ では先に各項の値を求めて配列に代入してから出力しましたが,同じfor文中で各項の値を求める処理と出力する処理を同時に行うようにします.また,その場合には配列を用意する必要がなくなりますね.以上により,解法 $1$ よりも短く書くことができます.

JavaScriptによる解答例を以下に示します.


let a = 0;

for (let i = 0; i < 10; i++) {
  a = 1 + i*2;
  document.write(a); 
  if (i < 9) document.write(" ");
}

fibonacci

問題

以下の漸化式で定められるフィボナッチ数列の第 $30$ 項 $a_{30}$ を求めてください. ただし,宣言するのはfor文中も合わせて変数 $3$ つのみ,または要素数 $2$ の配列 $1$ つおよび変数 $1$ つのみ,であることが望ましいです.

出力

ブラウザに答えを出力してください.

解説

開く

問題文中に示されている漸化式の通り,フィボナッチ数列 $a$ において, $a_n\ (n\geqq3)$ はその $1$ つ前の項 $a_{n-1}$ と $2$ つ前の項 $a_{n-2}$ の和で求められます.ここで,要素数 $30$ の配列を宣言したくなりますが,現在授業で習っている範囲だと自らの手で $30$ 個の要素を入力しなければなりません.とても大変です.なので,以下のように工夫しましょう.

解法 $1$ : 変数を用いる方法

変数を用いて書いてみましょう.まず,問題を解く上で,for文における毎度の処理で保持する必要がある値はfor文中の変数 $i$ を除いて $2$ つであることを確認しましょう.漸化式で示されていた式は $a_n=a_{n-1}+a_{n-2}\ (n\geqq3)$ でしたが, $a_{n-1}, a_{n-2}$ の値を例えばそれぞれ $x, y$ とし, $x$ と $y$ の和を一方の変数に代入することで, $2$ つの変数(とfor文中の変数 $i$ )のみで問題文の処理を実現することができます.次に,漸化式にそって計算していきましょう.はじめに,それぞれ $a_1, a_2$ の値で初期化した $2$ つの変数を宣言します.(ここでは $x, y$ とします.)あとはfor文を用いて $i=3, \ldots, 30$ まで回し,if文で場合分けして、例えば以下のように処理していきましょう.

  • for文 $(i=3,\ldots, 30)$ 内において,
    • $i$ を $2$ で割った余りが $0$ ならば $x$ に $x+y$ を代入
    • $i$ を $2$ で割った余りが $1$ ならば $y$ に $x+y$ を代入

そして,最後に $a_{30}$ の値になっている変数(この場合は $x$ )を出力すればよいですね.

以上により,答えは832040であると求めることができます.

JavaScriptによる解答例を以下に示します.


let x = 1, y = 1;

for (let i = 3; i <= 30; i++) {
  if (i%2 == 0) x = x + y;
  else if (i%2 == 1) y = x + y;
}

document.write(x);

解法 $2$ : 配列を用いる方法

配列を用いて書いてみましょう.こちらの方が少し短めに書くことができます.まず,それぞれの要素を $a_1, a_2$ で初期化した,要素数 $2$ の配列を宣言します.(ここでは $s$ とします.)次に,解法 $1$ と同様にfor文を回していきます.for文を用いて $i=3, \ldots, 30$ まで回し,例えば以下のように処理していきましょう.

  • for文 $(i=3,\ldots, 30)$ 内において,
    • $i$ を $2$ で割った余りが $0$ ならば $s_0$ に $s_0+s_1$ を代入
    • $i$ を $2$ で割った余りが $1$ ならば $s_1$ に $s_0+s_1$ を代入

ここで,if文を用いて場合分けしてもよいですが,余りの値をそのまま $s$ の添え字にすることで,より簡単に書くことができます.そして,最後に $a_{30}$ の値になっている $s$ の要素(この場合は $s_0$ )を出力すればよいですね.

JavaScriptによる解答例を以下に示します.


let s = [1, 1];

for (let i = 3; i <= 30; i++) {
  s[i%2] = s[0] + s[1];
}

document.write(s[0]);

*1.^ Metamoji では「プログラミング問題 by Juten10x」という名称を用いていました