けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 211 A - Blood Pressure (灰色, 100 点)

double 型変数の練習!

問題概要

2 つの数  A, B が与えられる。

 \displaystyle \frac{A - B}{3} + B

の値を出力せよ。なお、絶対誤差または相対誤差が  10^{-5} 以下であれば正解とみなされる。

解法

普段は整数型を扱うことが多いけど、今回は浮動小数点型を扱おう。そして、小数点以下  5 位以下まで出力するようにしよう。たとえば C++ では

cout << fixed << setprecision(5) << (出力する値) << endl;

というように書ける。

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    double A, B;
    cin >> A >> B;
    cout << fixed << setprecision(5) << (A - B) / 3 + B << endl;

AtCoder ABC 210 A - Cabbages (灰色, 100 点)

基本情報などでもよく問われる構造の問題!

問題概要

キャベツ 1 個を  X 円で買える。ただし、 A 個以上買う場合は 1 個  Y 円で買える ( Y \lt X)。

キャベツを  N 個買うときの価格を求めよ。

解法

  •  N \ge A である場合
    • 最初の  A 個の分: X \times A
    • 残りの  N - A 個の分: Y \times (N - A)
  •  N \lt A である場合
    •  X \times N

と求められます。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int N, A, X, Y;
    cin >> N >> A >> X >> Y;
    
    if (N >= A)
        cout << X * A + Y * (N - A) << endl;
    else
        cout << X * N << endl;
}

ABS PracticeA - Welcome to AtCoder

ABS の筆頭に登場する問題。整数型変数と文字列型変数の入力を受け取って、出力する練習をする問題。

問題概要

整数  a, b, c と、文字列  s が次の形式で標準入力で与えられます。

a
b c
s

 a+b+c の計算結果と、文字列  s を一行に並べて表示せよ。

解法

言語によって、標準入出力の仕様を確認しておきましょう!

ここでは C++ の解答例を示します。C++ では、入力における「改行」は気にせずに入力を受け取れます。次のコードの

cin >> a >> b >> c >> s;

というように、4 個のデータをまとめて受け取れます。

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a, b, c;
    string s;
    cin >> a >> b >> c >> s;
    cout << a+b+c << " " << s << endl;
}

AtCoder ABC 209 A - Counting (灰色, 100 点)

とても教育的な問題!

問題概要

整数  A, B が与えられる。

 A 以上  B 以下の整数は何個あるか?

解法

まず、 A \gt B の場合は、 A 以上  B 以下の整数は存在しないことに注意しよう。この場合は 0 個と答えれば良い。

それでは、 A \le B としよう。この場合は、 A 以上  B 以下の整数の個数は、


 B - A + 1


となる。 B - A ではないことに注意しよう。これはもう憶えてしまっても良いくらいだと思う。とても大事な考え方だ!

具体例をあげると、たとえば  A = 3 B = 7 のとき、3 以上 7 以下の整数は

3, 4, 5, 6, 7

の 5 個ある。7 - 3 + 1 = 5 より、確かに合っている。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int A, B;
    cin >> A >> B;
    
    if (A <= B)
        cout << B - A + 1 << endl;
    else
        cout << 0 << endl;
}

AtCoder ABC 208 A - Rolling Dice (灰色, 100 点)

「この数からこの数の間の数はすべて作れる」という考え方をする問題。この考え方は、より高度な問題では頻出!

問題概要

1〜6 の目が出るサイコロを  A 回振った。

出た目の総和が  B になることがありうるかどうかを判定せよ。

解法

これは難しい!!!

こういう時には、「出た目の総和が  B にできない場合ってどんな場合だろう......」と考えてみると、活路が開けることが多い。

たとえば、 A = 3 B = 20 の場合はあり得ない。なぜなら、3 回の目の和として考えられる最大値は

 6 \times 3 = 18

であり、それを超過しているからだ。また、 A = 3 B = 2 の場合もあり得ない。なぜなら、3 回の目の和として考えられる最小値は

 1 \times 3 = 3

であり、それよりも小さいからだ。

一般に、 A 回ふって出た目の和の最小値は  A、最大値は  6A になるから、次のことが言える。


 A \le B \le 6A でなければならない


 A 6A の間はすべて作れること

では、この  A 6A の間の数はすべて作れるだろうか? この答えは Yes だ!!!!!

考えやすくするため、 B 個のアメを  A 人に配るという設定にして考えてみよう。ただし、1 人のもらう個数は 1〜6 個のいずれかでなければならないとしよう。

たとえば  A = 3 B = 14 という場合を考えてみよう。

 14 \div 3 = 4 あまり 2

であることに注意しよう。

よって、14 個のアメをまず 3 人に 4 個ずつ配り、そして残った 2 個を 2 人に配れば良い。つまり、

 5 + 5 + 4 = 14

となる。 A = 3 B = 14 の場合はこうして実現できた。

他に、一般に、 A \le B \le 6A さえ満たしていれば、同様の方法で実現できる。

まとめ

以上から、次の条件を満たせば "Yes"、そうでなければ "No" だ。


 A \le B \le 6A


コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int A, B;
    cin >> A >> B;
    
    int min_value = A;
    int max_value = 6 * A;
    
    if (min_value <= B && B <= max_value)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}