Tenka1 Programmer Contest 2019 E問題:Polynomial Divisors

問題. Polynomial Divisors

 n 次の整数係数多項式  f(x) = a_n x^n + a_{n - 1} x^{n - 1} + \cdots + a_0 が与えられる.任意の整数  x に対して  f(x) p の倍数となるような素数  p をすべて求めよ.

制約 0 \le n \le 10^4,  |a_i| \le 10^9,  a_{n} \neq 0

解法

自力で解けなかったので 解説youtube)を参考にした.

 
素数  p が任意の整数  x に対して  f(x) \equiv 0 \pmod p を満たすかを判定する.フェルマーの小定理 より  x^{p - 1} \equiv 1 \pmod p を満たすので, p を剰余とした演算のもとでは  f p - 2 次の整数係数多項式
  f(x) = a_0 + (a_{p - 1} + a_{2p - 2} + \cdots) x^0 + (a_1 + a_{p} + \cdots ) x^1 + (a_2 + a_{p + 1} \cdots) x^2 + \cdots + (a_{p - 2} + a_{2p - 3} + \cdots) x^{p - 2}
となる.一般に,複素係数の  n多項式 n 個の複素根を持つ(代数学の基本定理とその初等的な証明 | 高校数学の美しい物語).このとこから, p - 2 次の整数係数多項式は高々  p - 2 個以下の整数根しか持つことができない.したがって,任意の整数  x に対して  x f(x) の根( f(x) p の倍数)となるための必要十分条件は,各係数が  p の倍数となることである.以上から,素数  p に対して  p が答えに含まれるかを  O(n) 時間で判定することができた.

次に,解の候補となる素数の範囲を調べる.演算を  p の剰余のもとで行うとき,多項式  f p - 2 次の多項式となったので, n + 2 \le p のときは各係数が  p の倍数となるかを判定することと等しくなる.また, a_{n} \neq 0 が保証されているので調べる素数 n + 1 以下の素数と, n + 2 以上の  |a_{n}| の素因数のみで十分である.

計算時間 O(n^2 + n \, d(| a_{n} |)) d(x) x の約数の個数; d(|a_{n}|) \le \log_2(|a_{n}|)

解説を読んだ後でも, a_0 x^0 の係数でまとめて WA 連発したので反省.
 |a_n| の素因数の代わりに  f(1) = a_0 + a_1 + \ldots + a_n の素因数を候補としている人がいた(こちらの方が先に思いつきやすそう).
自力で解けたら楽しいだろうな.