メモ帳

楽しいアウトプットの場所

Nim言語でABC181 A~Dを解く!!

Nim言語でABC181を解いたコードと解説を載せていきます。
atcoder.jp

A問題 Heavy Rotation

問題文
高橋くんは今、白い服を着ています。 高橋くんは、白い服を着た次の日には黒い服を、黒い服を着た次の日には白い服を着ます。 N 日後には何色の服を着るでしょうか?
制約
Nは整数である
\(1\leq N \leq 30\)

import strutils
let read = iterator: string {.closure.} =
  while true:
    for s in stdin.readLine.split:
      yield s

let N = read().parseInt

if N mod 2 == 0:
    echo "White"
else:
    echo "Black"

解説
上5行はおまじないです。興味があったら調べてみてください。以下のコードではこの5行を省略します。 偶数と奇数で場合分けする。nimでは、x mod yでxをyで割った余りが求められます。

B問題 Trapezoid Sum

何も書かれていない黒板があります。 高橋くんは N 回の操作を行い、黒板に整数を書きます。 i 回目の操作では、 A i 以上 B i 以下の整数すべてを 1 個ずつ、合計 B i − A i + 1 個の整数を書きます。 N 回の操作を終えたときの、黒板に書かれた整数の合計を求めてください

制約
入力はすべて整数 1≤N≤105、1≤Ai≤Bi≤106

解答のコードは以下の通りです。ただし、マクロの部分のコードを省略しています。

var sum = 0
let N = read().parseInt

for i in 0..<N:
    let a, b = read().parseInt
    sum += (a+b)*(b-a+1)div 2
echo sum

解説
等差数列の和の公式、a:初項、b:末項、N=(b-a+1):項数にあてはめます。
$$ S_{N}=\frac{(a+b)*N}{2} $$ for i in 0..<N:は, for(int i=0; i<N; i++)と同じような意味です。また、div 2は2で割った時に小数点以下を切り捨てて、整数にする演算です。Pythonで言うところの//になります。

C問題 collinearity

import strutils
let read = iterator: string {.closure.} =
  while true:
    for s in stdin.readLine.split:
      yield s
proc scan() : int =read().parseInt
#proc scanf() : float =read().parseFloat
#-----------------------------------------------------------------------------------#
var
  n = scan()
  x = newseq[int](n)
  y = newseq[int](n)

for i in 0..<n:
  (x[i], y[i]) = (scan(), scan())

for i in 0..<n:
  for j in i+1..<n:
    for k in j+1..<n:
      let
        x2 = x[j]-x[i]
        y2 = y[j]-y[i] 
        x3 = x[k]-x[i]
        y3 = y[k]-y[i] 
      if (x2*y3 == x3*y2):
          echo "Yes"
          quit()
echo "No"

D問題 Hachi

import unicode 
let s = readLine(stdin)
if len(s) < 3:
  for num in countup(8, 96, 8):
    #if (num == s.parseInt) or (num == reversed(s).parseInt):
    if $num == s or $num == reversed(s):
      echo "Yes"
      quit()
  echo "No"
  quit()

var s_cnt = newseq[int](300)
for ch in s:
  s_cnt[ord(ch)]+=1

for num in countup(104, 999, 8):
  var num_cnt = newseq[int](300)
  var ok = true
  for ch in $num:
    num_cnt[ord(ch)]+=1
  for i in 0..<300:
    if s_cnt[i] < num_cnt[i]:
      ok = false 
  if ok:
    echo "Yes"
    quit()
echo "No"