No.661 ハローキティはりんご3個分
はじめに
競技プログラミング、yukicoder
No.661 ハローキティはりんご3個分
言語はC#
何かあればTwitter→@pirorirori_n712まで
問題
入力:Nxの数+Nx(りんご1つ分を1とする)を数分
Nxは3nまたは8nまたは10n(1≤Nx≤1000000 )の数字
出力:与えられたNxがキティ(りんご3つ分を1とする)いくつ分の重さであるか
ただし、8の倍数である場合は、「iki」
10の倍数である場合は「sugi」、
8の倍数かつ10の倍数である場合には「ikisugi」
を出力する
解き方
文章から、入力の数字Nxによって出力させるものを分けていけばいいことが分かる。
①if文で場合分けをする1(40で割る、8・10で割る、3で割る)
②if分で場合分けをする2(8で割る、10で割る、3で割る)
③その他の解き方(他の方の解答もあるのでメモ程度)
①if文で場合分けをする1
問題の定義から、数字の出力よりも文字の出力を優先させる。
つまり、優先順位は以下のようになる。
①「ikisugi」8の倍数かつ10の倍数である場合
②「iki」8の倍数である場合、「sugi」10の倍数である場合
③Nxがキティいくつ分の重さであるかの値
①について
8の倍数かつ10の倍数である場合なので、
当てはまるNxは8と10の最小公倍数の倍数であることが分かる。
すなわち、Nxを8と10の最小公倍数である40で割って、あまりがでないものが①に当てはまる。
または、8と10それぞれで割って
どちらでもあまりが出ないという解き方もできる(→Nx%8==0&&Nx%10==0)
②について
Nxが8の倍数であれば「iki」、Nxが10の倍数であれば「sugi」なので
Nxを8、或いは10で割ってあまりが出なければここの出力となる。
なお、8の倍数と10の倍数は同率の優先度となっているが
先に①で8の倍数かつ10の倍数を出しているので
この時点で、8と10どちらの倍数にもなり得る値は流れてこない。
そのため、どちらから割っても問題はない。
③について
Nx(りんご1つを1とする)をキティ(リンゴ3つを1とする)という単位に
直した際にいくつになるかを数値で出力する。
1キティはリンゴ3つ分、すなわち
Nxが3のとき1キティとなる。
与えられたNxが何キティになるのかはNxを3で割れば分かる。
なお、問題文からNxは3nまたは8nまたは10nということが確定しているので
③に流れてくる数字は全て3の倍数であり、3で割り切れる数である。
以上をもとにコードを書いていく。
コード例
using System; class No661{ static void Main(string[] args){ //入力の文字を保存 var s=Console.ReadLine(); //string型の入力をint型に変換 var num=Int32.Parse(s); //numが0以上である限りループを回す、 //ループの最後で1ずつnumをマイナスしているのでnum回(与えられたNxの回数分)回ります //for(int i=0;i<num;++i)でも同じことができます while(num>0){ //入力されたNxをint型に変換して変数weightに保存 var weight=Int32.Parse(Console.ReadLine()); //もしweightが40で割り切れたら if(weight%40==0){ //「ikisugi」を出力 Console.WriteLine("ikisugi"); } //もしweightが10で割り切れたら else if(weight%10==0){ //「sugi」を出力 Console.WriteLine("sugi"); } //もしweightが8で割り切れたら else if(weight%8==0){ //「iki」を出力 Console.WriteLine("iki"); } //上のどれにも当てはまらない、 //すなわち8或いは10の倍数ではないもの3n else{ //weightを3で割ってキティ単位での値を出す weight=weight/3; //キティ単位の値を出力 Console.WriteLine(weight); } //ループの最後にnumから1を引く num--; } } }
少し整理して
using System; class No661{ static void Main(string[] args){ //string型の入力をint型に変換して変数numに保存 var num=Int32.Parse(Console.ReadLine()); //numが0以上である限りループを回す、 //ループの最後で1ずつnumをマイナスしているのでnum回(与えられたNxの回数分)回ります //for(int i=0;i<num;++i)でも同じことができます while(num>0){ //入力されたNxをint型に変換して変数weightに保存 var weight=Int32.Parse(Console.ReadLine()); //もしweightが40で割り切れたら if(weight%40==0){ //「ikisugi」を出力 Console.WriteLine("ikisugi"); } //もしweightが10で割り切れたら else if(weight%10==0){ //「sugi」を出力 Console.WriteLine("sugi"); } //もしweightが8で割り切れたら else if(weight%8==0){ //「iki」を出力 Console.WriteLine("iki"); } //上のどれにも当てはまらない、 //すなわち8或いは10の倍数ではないもの3n else{ //weightを3で割ってキティ単位での値を出力 Console.WriteLine(weight/3); } //ループの最後にnumから1を引く num--; } } }
②if分で場合分けをする2
①の変形バージョン
改行なしのConsole.WriteLine()を使って解く。
Nxが8と10で割り切れた場合の出力は「ikisugi」、
8で割り切れた場合の出力は「iki」
10で割り切れた場合の出力は「sugi」
そのため、8で割り切れ、かつ10で割り切れる場合は「iki」と「sugi」を改行なしで
出力することによって「ikisugi」を出力することができる。
場合分けは上から順に以下のようになる。
①8で割り切れる場合
→ここで改行なしの「iki」を出力
②10で割り切れる場合
→ここで「sugi」を出力する
③8でも10でも割り切れないNx(3n)を3で割る
コード例
using System; class No661{ static void Main(string[] args){ //string型の入力をint型に変換して変数numに保存 var num=Int32.Parse(Console.ReadLine()); //numが0以上である限りループを回す、 //ループの最後で1ずつnumをマイナスしているのでnum回(与えられたNxの回数分)回ります //for(int i=0;i<num;++i)でも同じことができます while(num>0){ //最後の3nしか入らない部分に、3n以外のものが入らないようにフラグを設定 //8或いは10の倍数だったらフラグをtrueにしておく var flg=false; //入力されたNxをint型に変換して変数weightに保存 var weight=Int32.Parse(Console.ReadLine()); //もしweightが8で割り切れたら if(weight%8==0){ //「iki」を出力 Console.Write("iki"); flg=true; } //もしweightが10で割り切れたら if(weight%10==0){ //「sugi」を出力 Console.Write("sugi"); flg=true; } //上のどれにも当てはまらない、 //すなわち8或いは10の倍数ではないもの3n //フラグがfalseのままなら8の倍数でも10の倍数でもない3nであると言える if(!flg){ //weightを3で割ってキティ単位での値を出力 Console.Write(weight/3); } //改行をする Console.WriteLine(); //ループの最後にnumから1を引く num--; } } }
③その他の解き方
他の方の解答を見て知ったので
詳しい解説は避けますが
上にあげた12の方法以外にも
先に8と10で割ってしまい、結果をbool型の変数に保存
その結果で出力を決めるという方法もありました。
またif分は、条件演算子にすると場合分けを一行で行うことができます。