導入
(atcoderのある問題の文章)
ただし、答えは非常に大きくなる可能性があるので、
(10^9+7)で割った余りを出力してください。
...ふむふむ,なるほど,求めた解が大きくなると表示できないから表示する際に10^9+7で割った余りを出せばいいんやね.
(問題解き終わった後(tle連発した),解答を見る)
N = int(input())
C = list(map(int, input().split()))
C.sort()
ans=1
for i in range(N):
ans = ans * max(0, C[i] - i) % 1000000007
print(ans)
...!最後に10^9+7で割るんじゃァなく,掛ける段階で毎回10^9+7で割ってるッ...!
これで正しい解が出るのというのかッ!非自明ッ!反直感ッ!
疑問点
$x_i$を$q$で割った際の商と余りを,それぞれ,$y_i,\ m_i(<q)$で表すとする.上記の現象を数式を使って表現すると,
\begin{align}
&\prod_{i=1}^Nx_i \equiv \prod_{i=1}^Nm_i\: \mod q\\
&where\ x_i = y_iq + m_i\ (i = 1,...,N)\\
\end{align}
となります.これが実際成立するのかというのが疑問点です.立式までできると後は簡単です.高校数学です.左辺と右辺をそれぞれ$q$で割った余りが一致するかを確かめれば良いだけです.
確かめる
では,実際に確かめてみましょう.右辺は
\begin{align}
\prod_{i=1}^Nx_i &= \prod_{i=1}^N(y_iq + m_i)\\
&=zq + \prod_{i=1}^Nm_i\\
\end{align}
と変形できます.ここで,zは$\prod_{i=1}^N(y_iq + m_i)$を展開した際に,(qを含む項の和)/qとして定義しています.また,$q,\ m_i$はそれぞれ互いに素であるため,$q,\ \prod_{i=1}^Nm_i$も互いに素です.以上より,
\begin{align}
&\prod_{i=1}^Nx_i \equiv \prod_{i=1}^Nm_i\: \mod q\\
&where\ x_i = y_iq + m_i\ (i = 1,...,N)\\
\end{align}
が確かめられました👏
以上から,最後に10^9+7で割ることと,掛ける段階で毎回10^9+7で割るのは結果として同じってコト!?(そもそもこんな処理が必要になるほど大きい数字は保持しきれないから,毎回余りとる必要あるよね)
終わりに
合同式を忘れた大人はこの程度でつまずく...!