AtCoder に登録したら解くべき精選過去問 10 問を VB.Net で解いてみた


実装リンク集 https://qiita.com/drken/items/6edb1c0542d4c3b7179c
問題一覧 https://abs.contest.atcoder.jp/assignments

|私の実装|記事|
|:--|:--|
|Ruby (私家版)|https://qiita.com/cielavenir/items/c0a45b6b87c411b60b93|
|Swift|https://qiita.com/cielavenir/items/b90a94dce60a620fa2dc|
|C|https://qiita.com/cielavenir/items/ee1e47b844d05dcfc66e|
|VB.Net|https://qiita.com/cielavenir/items/7ddf5e9bac02daf72159|
|Pascal|https://qiita.com/cielavenir/items/530270ac4affca435442|
|Perl|https://qiita.com/cielavenir/items/4d16ba1be4ad6847a914|
|MoonScript/Lua|https://qiita.com/cielavenir/items/6553531e230f39cd6a3d|

# 解答

## 例題 PracticeA

https://practice.contest.atcoder.jp/tasks/practice_1

C\#と違って、VBはある程度の型変換は自動でやってくれます。

文字列を分割するには、Split()します。

```vb:0.vb
module practiceA
  sub Main(ByVal args() as String)
    dim a,b,c as integer
    dim s as string
    dim arr(2) as string
    a=Console.ReadLine()
    arr=Split(Console.ReadLine())
    b=arr(0):c=arr(1)
    s=Console.ReadLine()
    Console.Write(a+b+c)
    Console.WriteLine(" "+s)
  end sub
end module
```

## 第１問 ABC086A Product

https://abc086.contest.atcoder.jp/tasks/abc086_a

VBのIfは文でもあり演算子でもあります。

```vb:1.vb
module ABC086A
  sub Main(ByVal args() as String)
    dim a,b as integer
    dim arr(2) as string
    arr=Split(Console.ReadLine())
    a=arr(0):b=arr(1)
    Console.WriteLine(If(a*b mod 2 > 0,"Odd","Even"))
  end sub
end module
```

## 第２問 ABC081A Placing Marbles

https://abc081.contest.atcoder.jp/tasks/abc081_a

文字リテラルは`"1"c`のように作成します。


```vb:2.vb
module ABC081A
  sub Main(ByVal args() as String)
    dim s as string
    dim c,i as integer
    s=Console.ReadLine()
    c=0
    for i=0 to 2
      if s(i)="1"c then 'thenはなくても良い(以下では省略します)
        c=c+1
      end if
    next
    Console.WriteLine(c)
  end sub
end module
```

## 第３問 ABC081B Shift only

https://abc081.contest.atcoder.jp/tasks/abc081_b

arrの各要素に対し2で割ることが出来た回数の最小値です。
INF値として`1<<29`が使われていますが、2倍してオーバーフローしない中で簡潔に書ける数として競技プログラミングではよく使われます。

VBでは、整数除算は`\`です。また、剰余はmodです。

```vb:3.vb
module ABC081B
  sub Main(ByVal args() as String)
    dim i,n,x,r as integer
    r=1<<29
    n=Console.ReadLine()
    dim arr(n) as string
    arr=Split(Console.ReadLine())
    for i=1 to n
      dim r0 as integer
      r0=0
      x=arr(i-1)
      while (x mod 2)<1
        r0+=1
        x\=2
      end while
      if r>r0
        r=r0
      end if
    next
    Console.WriteLine(r)
  end sub
end module
```

## 第４問 ABC087B Coins

https://abc087.contest.atcoder.jp/tasks/abc087_b

500円玉と100円玉の枚数を全探索します。

VBのand/orは短絡評価を行いません。andalso/orelseを使いましょう。

```vb:4.vb
module ABC087B
  sub Main(ByVal args() as String)
    dim a,b,c,x,i,j,k,r as integer
    a=Console.ReadLine()
    b=Console.ReadLine()
    c=Console.ReadLine()
    x=Console.ReadLine()
    for i=0 to x\500
      for j=0 to (x-500*i)\100
        k=x-500*i-100*j
        if k mod 50=0 andalso c>=k\50 andalso a>=i andalso b>=j
          r+=1
        end if
      next
    next
    Console.WriteLine(r)
  end sub
end module
```

## 第５問 ABC083B Some Sums

https://abc083.contest.atcoder.jp/tasks/abc083_b

変数sは各i(j)を10で割れるだけ割って、その間に出た余りの和です。

```vb:5.vb
module ABC083B
  sub Main(ByVal args() as String)
    dim n,a,b,r,i,j,s as integer
    dim arr(3) as string
    arr=Split(Console.ReadLine())
    n=arr(0):a=arr(1):b=arr(2)
    r=0
    for i=1 to n
      s=0
      j=i
      while j>0
        s+=j mod 10
        j\=10
      end while
      if a<=s andalso s<=b
        r+=i
      end if
    next
    Console.WriteLine(r)
  end sub
end module
```

## 第６問 ABC088B Card Game for Two

https://abc088.contest.atcoder.jp/tasks/abc088_b

整数への変換はArray.ConvertAllで行っています。mono vbncではArray\#Select(Linq)が使えないためです。また、関数のアドレスはaddressofで取ってくる必要があります。

降順でソートしたら、符号を切り替えながら足しこんでいきます。

```vb:6.vb
module ABC088B
  sub Main(ByVal args() as String)
    dim n,i,r,t as integer
    n=Console.ReadLine()
    dim arrs(n) as string
    dim arr(n) as integer
    arrs=Split(Console.ReadLine())
    arr=Array.ConvertAll(of string,integer)(arrs,addressof Integer.Parse)
    Array.Sort(arr)
    Array.Reverse(arr)
    r=0
    t=1
    for i=1 to n
      r+=t*arr(i-1)
      t=-t
    next
    Console.WriteLine(r)
  end sub
end module
```

## 第７問 ABC085B Kagami Mochi

https://abc085.contest.atcoder.jp/tasks/abc085_b

```vb:7.vb
imports System.Collections.Generic
module ABC085B
  sub Main(ByVal args() as String)
    dim n,i as integer
    dim m as new Dictionary(of integer,integer)
    'HashSetは.Net3.5以降のため使えません
    n=Console.ReadLine()
    for i=1 to n
      m(Console.ReadLine())=1
    next
    Console.WriteLine(m.Count)
  end sub
end module
```

## 第８問 ABC085C Otoshidama

https://abc085.contest.atcoder.jp/tasks/abc085_c

1000円札と5000円札の枚数を全探索します。

```vb:8.vb
module ABC085C
  sub Main(ByVal args() as String)
    dim n,y,i,j,k as integer
    dim arr(2) as string
    arr=Split(Console.ReadLine())
    n=arr(0):y=arr(1)
    for i=0 to n
      for j=0 to n-i
        k=n-i-j
        if i*1000+j*5000+k*10000=y
          Console.WriteLine("{0} {1} {2}",k,j,i)
          return
        end if
      next
    next
    Console.WriteLine("-1 -1 -1")
  end sub
end module
```

## 第９問 ABC049C Daydream

https://abc049.contest.atcoder.jp/tasks/arc065_a

文字列を逆にして比較していきます。C\#と違って、StrReverse()で反転された文字列を得られます。

Substringする際は文字列長をチェックしなければなりません。

```vb:9.vb
module ABC049C
  sub Main(ByVal args() as String)
    dim T() as string = {"dream","dreamer","erase","eraser"}
    dim s as string
    dim i,c,l,k as integer
    for i=0 to 3
      T(i)=StrReverse(T(i))
    next
    s=StrReverse(Console.ReadLine())
    c=0
    l=s.Length
    while c<l
      k=-1
      for i=0 to 3
        if l-c>=T(i).Length andalso s.Substring(c,T(i).Length)=T(i)
          k=T(i).Length
          exit for
        end if
      next
      if k<0
        Console.WriteLine("NO")
        return
      end if
      c+=k
    end while
    Console.WriteLine("YES")
  end sub
end module
```

## 第10問 ABC086C Traveling

https://abc086.contest.atcoder.jp/tasks/arc089_a

dx+dyがdt以下かつdtとの偶奇が一致。

```vb:10.vb
module ABC086C
  sub Main(ByVal args() as String)
    dim i,n,t,x,y as integer
    dim arr(3) as string
    n=Console.ReadLine()
    t=x=y=0
    for i=1 to n
      arr=Split(Console.ReadLine())
      dim t0,x0,y0 as integer
      t0=arr(0):x0=arr(1):y0=arr(2)
      dim dt,dx,dy as integer
      dt=t0-t:dx=x0-x:dy=y0-y
      if dx+dy>dt orelse (dt-dx-dy) mod 2>0
        Console.WriteLine("No")
        return
      end if
      t=t0:x=x0:y=y0
    next
    Console.WriteLine("Yes")
  end sub
end module
```