問題
提出コード(100点)
提出コード(満点)
100点から満点にもっていくことができず、解説を見ました…
言われれば確かにそうだけど~って感じですね。
解法
まずは100点までです。
の制約が少ないので、
について何かをするんだろうな、という気持ちになります。
すると、までの数の中を、
で割った余りによって分類すると、
そのあまりが等しい数については、最大公約数も等しいことがわかります。
ここで、と
の最小公倍数
は、おなじく
と
の最大公約数を
と表現したとき、
と表すことができます。
ので、で割った余りが
となるような数の総和をもとめ、そこに
をかけてあげれば、
で割った余りが
となるような数と、
の最小公倍数の総和が求められます。
これを、全てのに対して行えば、
でこの問題を解くことができます。
で割った余りが
となるような数は、
と表記することができます。
ここで、は
以上
(切り捨て)以下の数となります。
とおくと、
で割った余りが
となるような数の総和は、次のような計算式で求められます。
ということで、
をの
に対して行えば、答えを求めることができます。
で余りをとるタイミングや、割り算のタイミングに気を付けましょう。
ということで、ここまでは今回自分が自力でできた部分です。
ここから先は、素因数分解やらなんやらをするのかなぁと思っていたのですが…
解法自体は解説そのままです。
結局、のパターンは、
の約数にしかならないので、
~
の
について、
のパターンによって分けて総和を求め、あとは上と同じようにその総和と
の積を求めていけば答えが求まる、というものです。
そのために、まずはとなるような
の総和を求める方法を考えてみます。
これは、となるような
の総和を求め、最後に
倍したものと同じになります。
この総和は、包除原理を用いると、うまく計算することができます。
を素因数分解し、素因数の種類を洗い出します。今回は、例として3種類の素因数が存在し、
だったとします。
このとき、まずは ~
についての総和を求め、そこから
となるような
を引いていくことを考えます。
そして、この後は
- 素因数を奇数種類使用した数の倍数の総和を減算し、偶数種類使用した数の倍数の総和を加算する
という操作を行います。
今回の例だと、および
それぞれについて、
~
の中での倍数の総和を求め、減算し、
の倍数の総和については加算し直します。また、同じ素因数が2つ以上含まれているような場合(
など)は、無視します。
総和を求めるときは、上で行ったような総和の求め方と同じようなことをします。
の倍数は、
個(切り捨て)存在するので、これを
個としたときに、
という計算をすれば、総和を求めることができます。
また、素因数の種類および、同じ種類の素因数が2つ以上使用されているかどうかは、よくある素因数分解のアルゴリズムを用いれば、容易に調べることができます。
さて、となるような
の総和を求めることができたので、あとは
倍すれば
となるような
の総和になります。
あとは、全てのについて同じことを繰り返せば終わりです。
は、先ほどと同様よくある素因数分解等のアルゴリズムのようなものを使えば、
で洗い出すことができます。
ということで、これらの式をバグなく気合で組み立て計算すれば、この問題を解くことができます。