namespace QuadraticResidue { typedeflonglong qr_int64; structqr_complex { qr_int64 real, imag; qr_complex(qr_int64 R = 0, qr_int64 I = 0) : real(R), imag(I) {} }; qr_complex qrc_mul(qr_complex a, qr_complex b, qr_int64 sqrI, qr_int64 p){ returnqr_complex((a.real * b.real + a.imag * b.imag % p * sqrI) % p, (a.real * b.imag + a.imag * b.real) % p); } /// @brief Quick Power a^n in Mod-Meaning(mod p) qr_int64 qpow(qr_int64 a, qr_int64 n, qr_int64 p){ qr_int64 ret(1); while (n) { if (n & 1) ret = ret * a % p; a = a * a % p; n >>= 1; } return ret; } /// @brief Quick Power a^n in Mod-Meaning-Complex qr_complex qpow(qr_complex a, qr_int64 n, qr_int64 sqrI, qr_int64 p){ qr_complex ret(1); while (n) { if (n & 1) ret = qrc_mul(ret, a, sqrI, p); a = qrc_mul(a, a, sqrI, p); n >>= 1; } return ret; } /** * @brief Quadratic Residue, or Square Root in Mod-Meaning * @param a for equation x^2=a (mod p) * @param p mod num(need to be odd-prime) * @return -1 if no solution, 0 if one solution, and x if x^2 = a && (p-x)^2 = a (mod p) && x < p-x */ qr_int64 sqrt(qr_int64 n, qr_int64 p){ if (n == 0) return0; if (qpow(n, (p - 1) >> 1, p) == p - 1) return-1; qr_int64 a = rand(); while (qpow((a * a + p - n) % p, (p - 1) >> 1, p) == 1) a = rand(); qr_int64 res = qpow(qr_complex(a, 1), (p + 1) >> 1, (a * a + p - n) % p, p).real; return std::min(res, p - res); } }