尺のブログ?

やりたいことをやりたいです

AtCoder Beginner Contest 105

ABC105に参加しました。

均等に配れるなら0、そうでないなら1です。
実生活でも均等に配れるかわからないときって1枚ずつ配りますよね。
こうすれば均等に配れなくても差は1枚になります。

ある数が作れるなら、それより4大きい数も作れますので、
4で割った各あまりごとに作れる最小の数を探せばいいです。
実際、
あまり0→4
あまり1→21
あまり2→14
あまり3→7
が作れる最小の数になります。

よって、作れない数は
あまり0→なし
あまり1→1,5,9,11,17
あまり2→2,6,10
あまり3→3
となります。このときだけNoを出力して、それ以外はYesでいいです。

10進数を他の進数に直す方法は中学か高校でやったはずです。
それを-2に適用すればいいのですが、
プログラミング言語は負の数の割り算に関して気持ち悪い挙動(オイ)をするので
自分で割り算の方法を書いてやる必要があります。
目的は、N=P* (-2) + Rとなる整数PとR=0or1を見つけることです。

「l番目からr番目までの項の和がMの倍数」というのは、
「最初からr番目までの和から最初からl-1番目までの和を引いたものがMの倍数」、
つまり「最初からr番目までの和と最初からl-1番目までの和をそれぞれMで割った余りが等しい」ということになります。

数列の第0項を0と解釈して、i項目までの和をMで割った数列Sの各項に、
それぞれの数がいくつあるかを調べればいいです。
M項の配列をつくって、Mの「Sの値」番目の項を+1すれば、S内に各数がいくつずつあるかわかります。

しかし、Mが大きすぎてM項の配列は確保できません。
解説によれば、ハッシュマップというものを使うといいそうです。
私は知りませんでした。(泣)