AGC018: A - Getting Difference
問題
回りくどい解説
2つのボールからはじめて、できるだけ小さい値のボールを作ろうと思う。 例として (16, 6) を考える。 16 - 6 = 10 となり、更に小さい値を作るには、10 - 6 = 4 である。これは、16 - 2 * 6 = 4 (16 ÷ 6 = 2 あまり 4) をしている。 更に小さい値を作るには 6 - 4 = 2 をする (6 ÷ 4 = 1 あまり 2)
割れるだけ割る操作を、商とあまりを利用して繰り返すため、ユークリッド互除法を行っている。 このとき、2つの数から作ることのできる最も小さい数は、最大公約数である。 個の数の最大公約数を取ると、減算できる値の最小値がわかる。
入力の数列に が含まれないとき、 を作るためには より大きい数が数列に含まれている必要があることはすぐわかる。減算できる値の最小値=最大公約数 を用いて、 より大きい値 から減算によって が作れれば良い。作れる値は [tex:[M-G, M-2G, M-3G, ..., 0]] であり、この数列上に が含まれている必要がある。 (最小値でない作ることのできる値と最小値との最大公約数は、最小値に一致することに注意する) すなわち、 は の倍数である必要がある。 は数列の最大値のみ考えれば良い。
参考
上の解説読むより、以下の記事を一読したほうが良いです。
拡張ユークリッドの互除法 〜 一次不定方程式 ax + by = c の解き方 〜
コード
#define OK { cout << "POSSIBLE\n"; exit(0); } #define NG { cout << "IMPOSSIBLE\n"; exit(0); } int main() { int N, K; cin >> N >> K; vector<unsigned> a(N); cin >> a; if (N == 1 && a[0] == K) OK; unsigned g = a[0]; REP(i, 1, N) { if (a[i] == K) OK; g = __gcd(g, a[i]); } if (*max_element(a.begin(), a.end()) > K && K % g == 0) OK; NG; }