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

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

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;
}