私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「スイッチを反転しても同じ数だけ点灯する?」(CodeIQ)を参照してください。
家庭に必ずある分電盤。その中にはブレーカーがあり、家庭内の電気スイッチやコンセントなどにつながっています。
ここでは、1つのブレーカーが2つのスイッチにつながっているものとします。
また、それぞれのスイッチに対して電球が1つずつ付いています。
スイッチをONにしても、そのスイッチにつながるブレーカーでONになっていないと電球は点灯しません。
もちろん、ブレーカーがONになっていても、スイッチがONになっていないと電球は点灯しません。
今、m 個のブレーカーがあり、n 個の電球が点灯しています。
ここで、すべてのスイッチを反転させたとき、点灯している電球の数が同じでした。
(あくまでもスイッチ部分の反転のみで、ブレーカーを触ることはありません。)
このようなブレーカー、スイッチの状態が何通りあるか求めます。
例えば、m = 2, n = 1 のとき、以下のような16通りがあります。
(色が付いている部分が点灯している部分)
ブレーカー1 スイッチ1-1 スイッチ1-2 ブレーカー2 スイッチ2-1 スイッチ2-2 OFF OFF OFF ON OFF ON OFF OFF OFF ON ON OFF OFF OFF ON ON OFF ON OFF OFF ON ON ON OFF OFF ON OFF ON OFF ON OFF ON OFF ON ON OFF OFF ON ON ON OFF ON OFF ON ON ON ON OFF ON OFF ON OFF OFF OFF ON OFF ON OFF OFF ON ON OFF ON OFF ON OFF ON OFF ON OFF ON ON ON ON OFF OFF OFF OFF ON ON OFF OFF OFF ON ON ON OFF OFF ON OFF ON ON OFF OFF ON ON
同様に、m = 3, n = 2 のときは72通りがあります。
標準入力から m, n がスペース区切りで与えられたとき、上記のような状態が何通りあるか求め、そのパターン数を標準出力に出力してください。
なお、m, n はともに20以下の正の整数とします。
【入出力サンプル】
標準入力
2 1
標準出力
16
Rubyで解答しています。
#!/usr/bin/ruby def combin(m,n) ret = 1 m.downto(n+1){|i| ret *= i} (m-n).downto(2){|i| ret /= i} return ret end def solve(m,n) b_on = combin(m,n) p_on = combin(2*n,n) p_off = 2**(2*(m-n)) return b_on * p_on * p_off end # main while line = gets line.strip! next if line.empty? m,n = line.split.map{|a| a.to_i} p solve(m,n) end
入力値を数値にしてm, nをsolve()に渡し、結果を印字します。
考え方の通り、mCn * 2nCn * 22(n-m)を求めます。
mCnを求めます。
この問題はプログラムでパターンを数えることをせず、最初から考え方に書いた通りの数学の問題として解きました。と言うよりも、問題の操作を愚直にプログラムで実装するより数式を考えた方が容易でした。