AtCoder Beginner Contest 169(ABC169) A~Dの復習

順番が前後してしまいましたが、
例によって当時のお気持ちを書いて復習記事としたいと思います。
(1つ前のコンテストも参加しましたが、Dが解説ACできてないので……)

A - Multiplication 1

2つの整数が与えられるので、掛け算して出力する問題です。
まさかの初手REです。

a,b = map(int,input())
prin(a*b)

慢心。

a,b = map(int,input().split())
print(a*b)

たまにコンテスト前にこういう入力系を用意しておいたりするんですが、
それが裏目になってしまいました。
そもそもちゃんとサンプルを試すこと、動作してるものから持ってくること、
いろいろ慢心してますね。

B - Multiplication 2

整数の配列が与えられるので、全部掛け算する問題です。
ただし、1018を超える場合は-1を出力します。
2ペナしました。慢心です。

最初のコード(TLE)

N = int(input())
N_list = [int(i) for i in input().split()]
res = 1
for i in range(len(N_list)) :
    res = res * N_list[i]
 
if (res > 1000000000000000000) :
    print(-1)
else :
    print(res)

制約上Nは105ですから、
どうやら大きい数の掛け算で遅くなっていそうです。
(そう思ってるけど、全然裏付け取れてないのでちゃんと調べたほうがいいですね)
まあ1018を超えたら-1を出力するので途中でやめてしまえばいいやという
慢心が次のWAとなりました。

def main() :
 
    N = int(input())
    N_list = [int(i) for i in input().split()]
    res = 1
    for i in range(len(N_list)) :
        res = res * N_list[i]
        if (res > 1000000000000000000) :
            print(-1)
            return
    
    print(res)
 
main()

これはサンプルを試せば気づけたはずですが、
掛け算としては途中で1018を超えるけれども その後0が含まれているケースでは正しくない結果となります。
Nは105ですから、もう0が含まれてるかどうかは先に調べてしまいましょう。

def main() :
 
    N = int(input())
    N_list = [int(i) for i in input().split()]
    res = 1
 
    if (N_list.count(0) > 0) :
        print(0)
        return
 
    for i in range(len(N_list)) :
        res = res * N_list[i]
        if (res > 1000000000000000000) :
            print(-1)
            return
    
    print(res)
 
main()

これにてACです。 個人的な思いとしてC問題ならそれなりに警戒するので
最初のTLEくらいだったと思いますが、 B問題までは早く解かないとという気持ちがあるのでついサンプルを試さなくなりがちです。
考察も甘くなりがちかなあと思っています。
序盤の問題でもナメない。

C - Multiplication 3

A問題と類似ですが、今度は入力値が整数と小数となっています。
出力時に小数点以下は切り捨てします。
6ペナしました。何も言うまい。

こういう問題は一旦普通に提出してしまいがちです。1ペナ。
誤差問題であることはわかりますが、どういうデータで発現するかというのは
すぐにピンと来なかったので、ガチャガチャ試してみることにしました。5ペナ。
諦めてgoogleに旅に出て、ACとなりました。

from decimal import Decimal
 
A,B = input().split()
A = int(A)
B = int(Decimal(B) * 100)
 
s = A * B
s = s // 100
print(int(s))

Decimalというものがあるようです。便利。 ただ、よくよく考えるとBは小数点2桁固定ですから、
普通に文字列として扱って小数点を除いたほうがシンプルでした。
浮動小数点数として取得した時点で、100倍するとズレる値になってしまうので。

D - Div Game

与えられた整数Nに対して、条件を満たす整数zを選び、
N = N // zとする操作を何回繰り返せるか、という問題です。
D - Div Game

素因数分解して、数を数えればOKです。
25 = 21 * 22 * 22なので、2回操作できます。
最後の22はもう使った数なので操作の対象にできません。
Submission #13870826 - AtCoder Beginner Contest 169
コピペエンジニアと化してしまいました。
最初は素数テーブルを使って、、、とか考えてましたが、
素数テーブルの生成が遅かったので愚直にやるようにしました。
そのへんのコードもコピペなんですが、いいのかなあ……

結果

4AC10WA、1000点獲得で
3523位、パフォーマンス934でした。
余計なWAがなければ1000パフォだったかなあと思ってはいますが、
まあそこも実力かなあという気持ちです。
レートは+46で、596になりました。Highest更新です。
個人的に今回のセットはすごく楽しかったです。