AtCoder169振り返り(A〜C)
AtCoderの復習
結果
約40分の3完で終わり
4問目だけちょっとみて諦めました。(時間があれば復習しておきたい。)
2問目はオーバーフローの考慮が難しくつまづきました。
また自分が未だにJava7でコーディングしていることに気づいてしまい唖然。
次回からはJava8を使います。。。
成績
初めての茶色コーダ!
AtCoderの存在を知り参加し始めて約4ヶ月、ようやくです。
正直思ったよりも時間がかかってしまいました。
Ratingは以下の通り
文字の色が変わるんですね。(分かりづらいですが。。。)
なお今の実力では茶色上位まではいけますが緑コーダは難しそうです。
基礎的なアルゴリズムを学んでいく必要があるのでこれから色々勉強します。
問題
問1
問題が簡単すぎてビビりました。
int型でもオーバフローは起こり得ないので簡単に求められます。
■回答コード
import java.util.Scanner; public class Main { public static void main(String[] args) { try (Scanner scn = new Scanner(System.in)) { int a = scn.nextInt(); int b = scn.nextInt(); System.out.println(a * b); } } }
問2Multiplication 2
渡された引数を順に計算していって、最終的に10^18を超えるかかをチェックする問題です。
この問題ではオーバーフローをどのようにして考慮するか?というのが問題となります。
解説にある通りPythonならば128bitで計算が可能なのでそのまま実装できます。
一方でJavaの場合Java8以降であれば「Math.multiplyExact()」でオーバフローを検出できます。
が、なぜかいまだにローカル環境がJava7でやっていたので利用できませんでした。(というかlong型対応しているのでしょうか?)
私の場合かなり乱暴ですが、オーバフローをした場合
数値が10^18より大きいことに加えて、元の値より小さくなっていた場合を判断に組み込むことで実現しました。
(負数である場合、とした方がスマートでしたでしょうか。)
■回答コード
import java.util.Scanner; public class Main { public static void main(String[] args) { try (Scanner scn = new Scanner(System.in)) { int N = scn.nextInt(); long[] a = new long[N]; for(int i = 0; i < N; i++) { a[i] = scn.nextLong(); if(a[i] == 0) { System.out.println(0); System.exit(0); } } long max = (long) Math.pow(10, 18); max++; long tmp = a[0]; for(int i = 1; i < N; i++){ if(tmp * a[i] / max >= 1 || tmp * a[i] < tmp) { System.out.println(-1); System.exit(0); } tmp *= a[i]; } System.out.println(tmp); } } }
問3Multiplication 3
A×Bの小数点以下を切り捨てて、結果を整数として出力する。というシンプルな問題です。
直感的に浮動小数点で計算するとダメな気がしたので
BigDecimal型を利用しましたが問題なかったです。
解説では「(A × (B × 100))/100」でも誤差をなくすことができると記載があるので
こちらの方が綺麗なコードが掛けると思います。
■回答コード
import java.math.BigDecimal; import java.util.Scanner; public class Main { public static void main(String[] args) { try (Scanner scn = new Scanner(System.in)) { long A = scn.nextLong(); BigDecimal B = scn.nextBigDecimal(); System.out.println(BigDecimal.valueOf(A).multiply(B).setScale(0, BigDecimal.ROUND_DOWN)); } } }
解説