AtCoder Beginners Selectionの実施記録(C#)

## 概要

表題のプログラミング言語でAtCoder Beginners Selectionを実施記録した際の記録です
基本文法の学習が目的です

> https://atcoder.jp/contests/abs
> AtCoder Beginners Selectionとは？
> このコンテストは、「AtCoderに登録したけど何をしていいか分からない・・・！」という人に向けて作られた、初心者向け問題集です。
> 問題は、dr.kenさんの、「AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～」から選出しています。

基本的には以下ができれば大体の問題を解けるようになっている。

- 標準入力
- 標準出力
- 四則演算
- 条件分岐
- 文字列操作
- ループ
- 配列の操作
- 全通りの探索
- 組み込み関数等の利用
- ソート
- 集合
- 二次元配列の操作

## PracticeA - Welcome to AtCoder 

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

> 問題文
> 高橋君はデータの加工が行いたいです。
> 整数 a,b,cと、文字列 s が与えられます。 a+b+c の計算結果と、文字列 s を並べて表示しなさい。
>
> 制約
1≤a,b,c≤1,000
1≤∣s∣≤100
>
> 入力
> 入力は以下の形式で与えられる。
> a
> b c
> s
>
> 出力
> a+b+c と s を空白区切りで 1 行に出力せよ。

基本的な標準入力、標準出力、四則演算ができればOK

```c#:main.c#
using System;

namespace AtCoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // a, b, cをそれぞれ読み込む
            int a = int.Parse(Console.ReadLine());
            string[] inputs = Console.ReadLine().Split(' ');
            int b = int.Parse(inputs[0]);
            int c = int.Parse(inputs[1]);

            // sを読み込む
            string s = Console.ReadLine();

            // a+b+cとsを空白区切りで1行に出力する
            Console.WriteLine(a + b + c + " " + s);
        }
    }
}
```

## ABC086A - Product 

[ABC086A - Product](https://atcoder.jp/contests/abs/tasks/abc086_a)

>問題文
シカのAtCoDeerくんは二つの正整数 a,b を見つけました。 a と b の積が偶数か奇数か判定してください。
>
>制約
>1 ≤ a,b ≤ 10000
>a,b は整数
>
>入力
>入力は以下の形式で標準入力から与えられる。
>a b
>
>出力
積が奇数なら Odd と、 偶数なら Even と出力せよ。

基本的な標準入力、標準出力、四則演算、条件分岐ができればOK

```c#:main.c#
using System;

namespace Atcoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // 標準入力から a, b の値を取得する
            string[] input = Console.ReadLine().Split(' ');
            int a = int.Parse(input[0]);
            int b = int.Parse(input[1]);

            // a と b の積が奇数か偶数かを判定する
            if ((a * b) % 2 == 0)
            {
                Console.WriteLine("Even");
            }
            else
            {
                Console.WriteLine("Odd");
            }
        }
    }
}
```

## ABC081A - Placing Marbles 

[ABC081A - Placing Marbles ](https://atcoder.jp/contests/abs/tasks/abc081_a)

> 問題文
>すぬけ君は 1,2,3 の番号がついた 3 つのマスからなるマス目を持っています。各マスには 0 か 1 が書かれており、マス i には si が書かれています。
>すぬけ君は 1 が書かれたマスにビー玉を置きます。 ビー玉が置かれるマスがいくつあるか求めてください。
>
>制約
>s1 ,s2 ,s3 は 1 あるいは 0
>
>入力
>入力は以下の形式で標準入力から与えられる。
>s1s2s3 
>
>出力
>答えを出力せよ。
>
>入力例 1
>101
>
>出力例 1
>2


基本的な標準入力、標準出力、文字列操作ができればOK

```c#:main.c#
using System;

namespace Atcoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // s1s2s3 を文字列として読み込む
            string s = Console.ReadLine();

            // s の中に含まれる '1' の数を数える
            int count = 0;
            foreach (char c in s)
            {
                if (c == '1')
                {
                    count++;
                }
            }

            // 結果を出力する
            Console.WriteLine(count);
        }
    }
}
```

## ABC081B - Shift only 
[ABC081B - Shift only](https://atcoder.jp/contests/abs/tasks/abc081_b)

> 問題文
>黒板に N 個の正の整数 A1,...,AN が書かれています．
>すぬけ君は，黒板に書かれている整数がすべて偶数であるとき，次の操作を行うことができます．
>黒板に書かれている整数すべてを，2 で割ったものに置き換える．
>すぬけ君は最大で何回操作を行うことができるかを求めてください．
>
>制約
>1≤N≤200
>1≤Ai≤10^9
>
>入力
>入力は以下の形式で標準入力から与えられる。
>N
>A1 A2 ... AN
>
>出力
>すぬけ君は最大で何回操作を行うことができるかを出力せよ．
>
>入力例 1 
>3
>8 12 40
>
>出力例 1 
>2

基本的な標準入力、標準出力、四則演算、ループ、条件分岐、配列の操作ができればOK

```c#:main.c#
using System;

namespace AT4514
{
    class Program
    {
        static void Main(string[] args)
        {
            // N の値を読み込む
            int N = int.Parse(Console.ReadLine());
 
            // A の配列を作成して、それぞれの値を読み込む
            int[] A = new int[N];
            string[] line = Console.ReadLine().Split();
            for (int i = 0; i < N; i++)
            {
                A[i] = int.Parse(line[i]);
            }

            // 操作を行う回数を数える変数を用意する
            int count = 0;

            // 全ての数が偶数である限り、操作を繰り返す
            while (true)
            {
                bool isEven = true;
                for (int i = 0; i < N; i++)
                {
                    if (A[i] % 2 != 0)
                    {
                        isEven = false;
                        break;
                    }
                }

                // 全ての数が偶数でない場合、操作を終了する
                if (!isEven)
                {
                    break;
                }

                // 全ての数を2で割る
                for (int i = 0; i < N; i++)
                {
                    A[i] /= 2;
                }

                // 操作を行った回数をカウントアップする
                count++;
            }

            // 結果を出力する
            Console.WriteLine(count);
        }
    }
}
```

## ABC087B - Coins
[ABC087B - Coins](https://atcoder.jp/contests/abs/tasks/abc087_b)

> 問題文
>あなたは、500 円玉を A 枚、100 円玉を B 枚、50 円玉を C 枚持っています。 これらの硬貨の中から何枚かを選び、合計金額をちょうど X 円にする方法は何通りありますか。
>同じ種類の硬貨どうしは区別できません。2 通りの硬貨の選び方は、ある種類の硬貨についてその硬貨を選ぶ枚数が異なるとき区別されます。
>
>制約
>0≤A,B,C≤50
>A+B+C≥1
>50≤X≤20,000
>A,B,C は整数である
>X は 50 の倍数である
>
>入力
>入力は以下の形式で標準入力から与えられる。
>A
>B
>C
>X
>
>出力
>硬貨を選ぶ方法の個数を出力せよ。

基本的な標準入力、標準出力、四則演算、ループ、条件分岐、配列の操作、全通りの探索ができればOK

```c#:main.c#
using System;

namespace CoinChange
{
    class Program
    {
        static void Main(string[] args)
        {
            // 入力を受け取る
            int a = int.Parse(Console.ReadLine());
            int b = int.Parse(Console.ReadLine());
            int c = int.Parse(Console.ReadLine());
            int x = int.Parse(Console.ReadLine());

            // 硬貨を選ぶ方法の個数をカウントする変数
            int count = 0;

            // 500円玉を選ぶ全ての可能性を試す
            for (int i = 0; i <= a; i++)
            {
                // 100円玉を選ぶ全ての可能性を試す
                for (int j = 0; j <= b; j++)
                {
                    // 50円玉を選ぶ全ての可能性を試す
                    for (int k = 0; k <= c; k++)
                    {
                        // 選んだ硬貨の金額が X 円になっているかを判定する
                        if (i * 500 + j * 100 + k * 50 == x)
                        {
                            // X 円になっている場合はカウントを増やす
                            count++;
                        }
                    }
                }
            }

            // 結果を出力する
            Console.WriteLine(count);
        }
    }
}
```

## ABC083B - Some Sums
[ABC083B - Some Sums](https://atcoder.jp/contests/abs/tasks/abc083_b)

>問題文
>1 以上 N 以下の整数のうち、10 進法での各桁の和が A 以上 B 以下であるものの総和を求めてください。
>
>制約
>1≤N≤10^4 
>1≤A≤B≤36
>入力はすべて整数である
>
>入力
>入力は以下の形式で標準入力から与えられる。
>N A B
>
>出力
>1 以上 N 以下の整数のうち、10 進法での各桁の和が A 以上 B 以下であるものの総和を出力せよ。

基本的な標準入力、標準出力、四則演算、ループ、条件分岐、配列の操作、組み込み関数の利用、ができればOK

```c#:main.c#
using System;

namespace DigitSum
{
    class Program
    {
        static void Main(string[] args)
        {
            // N, A, Bを読み込む
            string[] input = Console.ReadLine().Split();
            int N = int.Parse(input[0]);
            int A = int.Parse(input[1]);
            int B = int.Parse(input[2]);

            // 総和を計算する
            long sum = 0;
            for (int i = 1; i <= N; i++)
            {
                int digitSum = GetDigitSum(i);
                if (digitSum >= A && digitSum <= B)
                {
                    sum += i;
                }
            }

            // 総和を出力する
            Console.WriteLine(sum);
        }

        // 数値xの10進法での各桁の和を計算する
        static int GetDigitSum(int x)
        {
            int sum = 0;
            while (x > 0)
            {
                sum += x % 10;
                x /= 10;
            }
            return sum;
        }
    }
}
```

## ABC088B - Card Game for Two
[ABC088B - Card Game for Two](https://atcoder.jp/contests/abs/tasks/abc088_b)

> 問題文
>N 枚のカードがあります. i 枚目のカードには, ai という数が書かれています.
>Alice と Bob は, これらのカードを使ってゲームを行います. ゲームでは, Alice と Bob が交互に 1 枚ずつカードを取っていきます. Alice が先にカードを取ります.
>2 人がすべてのカードを取ったときゲームは終了し, 取ったカードの数の合計がその人の得点になります. 2 人とも自分の得点を最大化するように最適な戦略を取った時, Alice は Bob より何点多く取るか求めてください.
>
>制約
>N は 1 以上 100 以下の整数
>ai(1≤i≤N) は 1 以上 100 以下の整数
>
>入力
>入力は以下の形式で標準入力から与えられる.
>N
>a1 a2 a3 ... aN
>
>出力
>両者が最適な戦略を取った時, Alice は Bob より何点多く取るかを出力してください.

基本的な標準入力、標準出力、四則演算、条件分岐、配列の操作、ループ、ソート、ができればOK

```c#:main.c#
using System;
using System.Linq;

namespace AtCoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // N 枚のカードがある
            int N = int.Parse(Console.ReadLine());

            // ai が書かれたカードを読み込む
            int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray();

            // 降順にソートする
            Array.Sort(a, (x, y) => y - x);

            // Alice の得点を計算する
            int AliceScore = 0;
            for (int i = 0; i < N; i += 2)
            {
                AliceScore += a[i];
            }

            // Bob の得点を計算する
            int BobScore = 0;
            for (int i = 1; i < N; i += 2)
            {
                BobScore += a[i];
            }

            // Alice の得点と Bob の得点の差を出力する
            Console.WriteLine(AliceScore - BobScore);
        }
    }
}
```

## ABC085B - Kagami Mochi 
[ABC085B - Kagami Mochi](https://atcoder.jp/contests/abs/tasks/abc085_b)

> 問題文
>X 段重ねの鏡餅 (X≥1) とは、X 枚の円形の餅を縦に積み重ねたものであって、どの餅もその真下の餅より直径が小さい（一番下の餅を除く）もののことです。例えば、直径 10、8、6 センチメートルの餅をこの順に下から積み重ねると 3 段重ねの鏡餅になり、餅を一枚だけ置くと 1 段重ねの鏡餅になります。
>ダックスフンドのルンルンは N 枚の円形の餅を持っていて、そのうち i 枚目の餅の直径は diセンチメートルです。これらの餅のうち一部または全部を使って鏡餅を作るとき、最大で何段重ねの鏡餅を作ることができるでしょうか。
>
>制約
>1≤N≤100
>1≤di≤100
>入力値はすべて整数である。
>
>入力
>入力は以下の形式で標準入力から与えられる。
>N
>d1
>​:
>dN
>
>​出力
>作ることのできる鏡餅の最大の段数を出力せよ。
>
>入力例 1 
>4
>10
>8
>8
>6
>
>出力例 1 
>3


基本的な標準入力、標準出力、四則演算、ループ、配列、集合、ができればOK

```c#:main.c#
using System;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 餅の枚数を読み込む
            int n = int.Parse(Console.ReadLine());

            // 餅の直径を読み込む
            int[] d = new int[n];
            for (int i = 0; i < n; i++)
            {
                d[i] = int.Parse(Console.ReadLine());
            }

            // 餅の直径を昇順に並び替える
            Array.Sort(d);

            // 鏡餅を作るために使用する餅の枚数
            int count = 1;

            // 最小の直径の餅から順番に見ていく
            for (int i = 1; i < n; i++)
            {
                // 現在の餅の直径よりも小さい餅が見つかった場合は、それらを使って鏡餅を作ることができる
                if (d[i] > d[i-1])
                {
                    count++;
                }
            }

            // 答えを出力する
            Console.WriteLine(count);
        }
    }
}
```

## ABC085C - Otoshidama
[ABC085C - Otoshidama](https://atcoder.jp/contests/abs/tasks/abc085_c)

>問題文
>日本でよく使われる紙幣は、10000 円札、5000 円札、1000 円札です。以下、「お札」とはこれらのみを指します。
>青橋くんが言うには、彼が祖父から受け取ったお年玉袋にはお札が N 枚入っていて、合計で Y 円だったそうですが、嘘かもしれません。このような状況がありうるか判定し、ありうる場合はお年玉袋の中身の候補を一つ見つけてください。なお、彼の祖父は十分裕福であり、お年玉袋は十分大きかったものとします。
>
>制約
>1≤N≤2000
>1000≤Y≤2×10^7
>N は整数である。
>Y は 1000 の倍数である。
>
>入力
>入力は以下の形式で標準入力から与えられる。
>N Y
>
>出力
>N 枚のお札の合計金額が Y 円となることがありえない場合は、-1 -1 -1 と出力せよ。
>N 枚のお札の合計金額が Y 円となることがありうる場合は、そのような N 枚のお札の組み合わせの一例を「10000 円札 x 枚、5000 円札 y 枚、1000 円札 z 枚」として、x、y、z を空白で区切って出力せよ。複数の可能性が考えられるときは、そのうちどれを出力してもよい。
>
>入力例 1 
>9 45000
>
>出力例 1 
>4 0 5

基本的な標準入力、標準出力、四則演算、ループができればOK

```c#:main.c#
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 入力を受け取る
            var input = Console.ReadLine().Split();
            var n = int.Parse(input[0]);
            var y = int.Parse(input[1]);

            // 全通り試す
            for (int i = 0; i <= n; i++)
            {
                for (int j = 0; j <= n - i; j++)
                {
                    int k = n - i - j;
                    if (10000 * i + 5000 * j + 1000 * k == y)
                    {
                        // 答えを出力する
                        Console.WriteLine($"{i} {j} {k}");
                        return;
                    }
                }
            }

            // 見つからなかった場合は -1 -1 -1 を出力する
            Console.WriteLine("-1 -1 -1");
        }
    }
}
```

## ABC049C - 白昼夢
[ABC049C - 白昼夢](https://atcoder.jp/contests/abs/tasks/arc065_a)

>問題文
>英小文字からなる文字列 S が与えられます。 Tが空文字列である状態から始め、以下の操作を好きな回数繰り返すことで S=T とすることができるか判定してください。
>
>制約
>1≦∣S∣≦10^5
>S は英小文字からなる。
>
>入力
>入力は以下の形式で標準入力から与えられる。
>S
>
>出力
>S=T とすることができる場合 YES を、そうでない場合 NO を出力せよ。
>
>入力例 1 
>erasedream
>
>出力例 1 
>YES

基本的な標準入力、標準出力、文字列操作ができればOK

```c#:main.c#
using System;

namespace AtCoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // 文字列Sを受け取る
            string t = Console.ReadLine();

            // 文字列Tを順に調べていき、dream、dreamer、erase、eraserのいずれかで終わっている場合は、それを削除する
            while (t.Length > 0)
            {
                if (t.EndsWith("dream"))
                {
                    t = t.Substring(0, t.Length - 5);
                }
                else if (t.EndsWith("dreamer"))
                {
                    t = t.Substring(0, t.Length - 7);
                }
                else if (t.EndsWith("erase"))
                {
                    t = t.Substring(0, t.Length - 5);
                }
                else if (t.EndsWith("eraser"))
                {
                    t = t.Substring(0, t.Length - 6);
                }
                else
                {
                    // dream、dreamer、erase、eraserのいずれでも終わっていない場合は、S=Tとすることができない
                    Console.WriteLine("NO");
                    return;
                }
            }
            // 文字列Tが空になった場合は、S=Tとすることができる
            Console.WriteLine("YES");
        }
    }
}
```

## ABC086C - Traveling
[ABC086C - Traveling](https://atcoder.jp/contests/abs/tasks/arc089_a)

> 問題文
>シカのAtCoDeerくんは二次元平面上で旅行をしようとしています。 AtCoDeerくんの旅行プランでは、時刻 0 に 点 (0,0) を出発し、 1 以上 N 以下の各 i に対し、時刻tiに 点 (xi,yi) を訪れる予定です。
>AtCoDeerくんが時刻 t に 点 (x,y) にいる時、 時刻 t+1 には 点 (x+1,y), (x−1,y), (x,y+1), (x,y−1) のうちいずれかに存在することができます。 その場にとどまることは出来ないことに注意してください。 AtCoDeerくんの旅行プランが実行可能かどうか判定してください。
>
>制約
>1 ≤ N ≤ 10^5 
>0 ≤ xi ≤ 10^5
>0 ≤ yi ≤ 10^5
>1 ≤ ti ≤ 10^5
>ti < ti+1 (1 ≤ i ≤ N−1)
>入力は全て整数
>
>入力
>入力は以下の形式で標準入力から与えられる。
>N
>t1 x1 y1
>​t2 x2 y2 
>:
>tN xN yN
>
>出力
>旅行プランが実行可能ならYesを、不可能ならNoを出力してください。
>
>入力例 1 
>2
>3 1 2
>6 1 1
>
>出力例 1 
>Yes
>
>入力例 2 
>1
>2 100 100
>
>出力例 2 
>No
>(0,0) にいる状態から 2 秒後に (100,100) にいるのは不可能です。
>
>入力例 3 
>2
>5 1 1
>100 1 1
>
>出力例 3 
>No



基本的な標準入力、標準出力、四則演算、ループ、二次元配列の操作、ができればOK

```c#:main.c#
using System;
using System.Linq;

namespace AtCoder
{
    class Program
    {
        static void Main(string[] args)
        {
            // 入力を読み込む
            int n = int.Parse(Console.ReadLine());
            int[][] points = new int[n][];
            for (int i = 0; i < n; i++)
            {
                points[i] = Console.ReadLine().Split().Select(int.Parse).ToArray();
            }

            // 最初の位置から順番に移動していき、それぞれの位置に到達できるかを確認する
            int x = 0, y = 0, t = 0;
            foreach (int[] point in points)
            {
                int dt = point[0] - t; // 現在地から次の位置に移動するまでにかかる時間
                int dx = point[1] - x; // 現在地から次の位置に移動するまでに必要なx方向の移動距離
                int dy = point[2] - y; // 現在地から次の位置に移動するまでに必要なy方向の移動距離

                // 移動時間よりも移動距離が大きければ、その位置には到達できない
                if (Math.Abs(dx) + Math.Abs(dy) > dt)
                {
                    Console.WriteLine("No");
                    return;
                }

                // 移動距離が偶数であれば、移動時間も偶数である必要がある
                // そうでなければ、奇数である必要がある
                if ((Math.Abs(dx) + Math.Abs(dy)) % 2 != dt % 2)
                {
                    Console.WriteLine("No");
                    return;
                }

                // 次の位置をセット
                x = point[1];
                y = point[2];
                t = point[0];
            }

            // すべての位置に到達できたら、Yesを出力
            Console.WriteLine("Yes");
        }
    }
}
```

# 参考

https://atcoder.jp/contests/abs