QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#124901 | #998. 素数分解 | GoatGirl98# | AC ✓ | 19ms | 4784kb | C++14 | 30.8kb | 2023-07-15 18:10:31 | 2023-07-15 18:10:33 |
Judging History
answer
// test only
#include <bits/stdc++.h>
template<typename...>using my_void_t = void;
template<>struct std::is_integral<__int128>: public std::true_type {};
template<>struct std::is_integral<__uint128_t>: public std::true_type {};
template<typename _Tp>constexpr int my_countr_zero(_Tp __x)noexcept {
constexpr auto _Nd = std::numeric_limits<_Tp>::digits;
if (__x == 0)
return _Nd;
constexpr auto _Nd_ull = std::numeric_limits<uint64_t>::digits;
constexpr auto _Nd_u = std::numeric_limits<unsigned>::digits;
if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_u)
return __builtin_ctz(__x);
else if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ull)
return __builtin_ctzll(__x);
else {
constexpr auto __max_ull = std::numeric_limits<uint64_t>::max();
uint64_t __low = __x & __max_ull;
if (__low)
return __builtin_ctzll(__low);
uint64_t __high = __x >> _Nd_ull;
return __builtin_ctzll(__high) + _Nd_ull;
}
}
template<typename _Clock, typename = my_void_t<typename _Clock::rep, typename _Clock::period, typename _Clock::duration, typename _Clock::time_point, decltype(_Clock::is_steady), decltype(_Clock::now())>>struct
__check_time_helper {
typename _Clock::time_point t;
double used;
__check_time_helper() {
used = 0;
} void start() {
t = _Clock::now();
} void stop() {
used += std::chrono::duration_cast<std::chrono::nanoseconds>(_Clock::now() - t).count() / 1e6;
}~__check_time_helper() {
fprintf(stderr, "time used: %.2lfms\n", used);
}
};
namespace OY {
template<uint64_t _BufferSize, uint64_t _BlockSize>class inputHelper {
public:
FILE *m_filePtr;
char m_buf[_BufferSize], *m_end, *m_cursor;
bool m_ok;
void flush() {
uint64_t a = m_end - m_cursor;
if (a >= _BlockSize)
return;
memmove(m_buf, m_cursor, a);
uint64_t b = fread(m_buf + a, 1, _BufferSize - a, m_filePtr);
m_cursor = m_buf;
if (a + b < _BufferSize) {
m_end = m_buf + a + b;
*m_end = EOF;
}
} public:
explicit inputHelper(const char *inputFileName): m_ok(true) {
if ((ptrdiff_t)inputFileName <= 0 || !*inputFileName)
m_filePtr = stdin;
else
m_filePtr = fopen(inputFileName, "rt");
m_end = m_cursor = m_buf + _BufferSize;
}~inputHelper() {
fclose(m_filePtr);
} static constexpr bool isBlank(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
} static constexpr bool isEndline(char c) {
return c == '\n' || c == EOF;
} const char &getChar_Checked() {
if (m_cursor < m_end)
return*m_cursor;
uint64_t b = fread(m_buf, 1, _BufferSize, m_filePtr);
m_cursor = m_buf;
if (b < _BufferSize) {
m_end = m_buf + b;
*m_end = EOF;
}
return*m_cursor;
} const char &getChar_Unchecked()const {
return*m_cursor;
} void next() {
++m_cursor;
} void setState(bool _ok) {
m_ok = _ok;
} template<typename _Tp, typename std::enable_if<std::is_signed<_Tp>::value &std::is_integral<_Tp>::value, int>::type = 0>inputHelper<_BufferSize, _BlockSize>
&operator>>(_Tp &ret) {
while (isBlank(getChar_Checked()))
next();
flush();
if (getChar_Unchecked() == '-') {
next();
if (isdigit(getChar_Unchecked())) {
ret = -(getChar_Unchecked() - '0');
while (next(), isdigit(getChar_Unchecked()))
ret = ret * 10 - (getChar_Unchecked() - '0');
} else
m_ok = false;
} else {
if (isdigit(getChar_Unchecked())) {
ret = getChar_Unchecked() - '0';
while (next(), isdigit(getChar_Unchecked()))
ret = ret * 10 + (getChar_Unchecked() - '0');
} else
m_ok = false;
}
return*this;
} template<typename _Tp, typename std::enable_if<std::is_unsigned<_Tp>::value &std::is_integral<_Tp>::value, int>::type = 0>inputHelper<_BufferSize, _BlockSize>
&operator>>(_Tp &ret) {
while (isBlank(getChar_Checked()))
next();
flush();
if (isdigit(getChar_Unchecked())) {
ret = getChar_Unchecked() - '0';
while (next(), isdigit(getChar_Unchecked()))
ret = ret * 10 + (getChar_Unchecked() - '0');
} else
m_ok = false;
return*this;
} template<typename _Tp, typename std::enable_if<std::is_floating_point<_Tp>::value, int>::type = 0>inputHelper<_BufferSize, _BlockSize>
&operator>>(_Tp &ret) {
bool neg = false, integer = false, decimal = false;
while (isBlank(getChar_Checked()))
next();
flush();
if (getChar_Unchecked() == '-') {
neg = true;
next();
}
if (!isdigit(getChar_Unchecked()) && getChar_Unchecked() != '.') {
m_ok = false;
return*this;
}
if (isdigit(getChar_Unchecked())) {
integer = true;
ret = getChar_Unchecked() - '0';
while (next(), isdigit(getChar_Unchecked()))
ret = ret * 10 + (getChar_Unchecked() - '0');
}
if (getChar_Unchecked() == '.') {
next();
if (isdigit(getChar_Unchecked())) {
if (!integer)
ret = 0;
decimal = true;
_Tp unit = 0.1;
ret += unit * (getChar_Unchecked() - '0');
while (next(), isdigit(getChar_Unchecked())) {
unit *= 0.1;
ret += unit * (getChar_Unchecked() - '0');
}
}
}
if (!integer && !decimal)
m_ok = false;
else if (neg)
ret = -ret;
return*this;
} inputHelper<_BufferSize, _BlockSize> &operator>>(char &ret) {
while (isBlank(getChar_Checked()))
next();
ret = getChar_Checked();
if (ret == EOF)
m_ok = false;
else
next();
return*this;
} inputHelper<_BufferSize, _BlockSize> &operator>>(std::string &ret) {
while (isBlank(getChar_Checked()))
next();
if (getChar_Checked() != EOF) {
ret.clear();
do {
ret += getChar_Checked();
next();
} while (!isBlank(getChar_Checked()) && getChar_Unchecked() != EOF);
} else
m_ok = false;
return*this;
} explicit operator bool() {
return m_ok;
}
};
template < uint64_t _BufferSize = 1 << 20 > class outputHelper {
FILE *m_filePtr = nullptr;
char m_buf[_BufferSize], *m_end, *m_cursor;
char m_tempBuf[50], *m_tempBufCursor, *m_tempBufDot;
uint64_t m_floatReserve, m_floatRatio;
public:
outputHelper(const char *outputFileName, int prec = 6): m_end(m_buf + _BufferSize) {
if ((ptrdiff_t)outputFileName <= 0 || !*outputFileName)
m_filePtr = stdout;
else
m_filePtr = fopen(outputFileName, "wt");
m_cursor = m_buf;
m_tempBufCursor = m_tempBuf;
precision(prec);
}~outputHelper() {
flush();
fclose(m_filePtr);
} void precision(int prec) {
m_floatReserve = prec;
m_floatRatio = pow(10, prec);
m_tempBufDot = m_tempBuf + prec;
} outputHelper<_BufferSize> &flush() {
fwrite(m_buf, 1, m_cursor - m_buf, m_filePtr);
fflush(m_filePtr);
m_cursor = m_buf;
return*this;
} void putChar(const char &c) {
if (m_cursor == m_end)
flush();
*m_cursor++ = c;
} void putS(const char *c) {
while (*c)
putChar(*c++);
} template<typename _Tp, typename std::enable_if<std::is_signed<_Tp>::value &std::is_integral<_Tp>::value, int>::type = 0>outputHelper<_BufferSize>
&operator<<(const _Tp &ret) {
_Tp _ret = _Tp(ret);
if (_ret >= 0) {
do {
*m_tempBufCursor++ = '0' + _ret % 10;
_ret /= 10;
} while (_ret);
do
putChar(*--m_tempBufCursor);
while (m_tempBufCursor > m_tempBuf)
;
} else {
putChar('-');
do {
*m_tempBufCursor++ = '0' - _ret % 10;
_ret /= 10;
} while (_ret);
do
putChar(*--m_tempBufCursor);
while (m_tempBufCursor > m_tempBuf)
;
}
return*this;
} template<typename _Tp, typename std::enable_if<std::is_unsigned<_Tp>::value &std::is_integral<_Tp>::value, int>::type = 0>outputHelper<_BufferSize>
&operator<<(const _Tp &ret) {
_Tp _ret = _Tp(ret);
do {
*m_tempBufCursor++ = '0' + _ret % 10;
_ret /= 10;
} while (_ret);
do
putChar(*--m_tempBufCursor);
while (m_tempBufCursor > m_tempBuf)
;
return*this;
} template<typename _Tp, typename std::enable_if<std::is_floating_point<_Tp>::value, int>::type = 0>outputHelper<_BufferSize>
&operator<<(const _Tp &ret) {
if (ret < 0) {
putChar('-');
return*this << -ret;
}
_Tp _ret = ret * m_floatRatio;
uint64_t integer = _ret;
if (_ret - integer >= 0.4999999999)
integer++;
do {
*m_tempBufCursor++ = '0' + integer % 10;
integer /= 10;
} while (integer);
if (m_tempBufCursor > m_tempBufDot) {
do
putChar(*--m_tempBufCursor);
while (m_tempBufCursor > m_tempBufDot)
;
putChar('.');
} else {
putS("0.");
for (int i = m_tempBufDot - m_tempBufCursor; i--;)
putChar('0');
}
do
putChar(*--m_tempBufCursor);
while (m_tempBufCursor > m_tempBuf)
;
return*this;
} outputHelper<_BufferSize> &operator<<(const char &ret) {
putChar(ret);
return*this;
} outputHelper<_BufferSize> &operator<<(const std::string &ret) {
putS(ret.data());
return*this;
}
};
template<uint64_t _BufferSize, uint64_t _BlockSize>inputHelper<_BufferSize, _BlockSize> &getline(
inputHelper<_BufferSize, _BlockSize> &ih, std::string &ret) {
ret.clear();
if (ih.getChar_Checked() == EOF)
ih.setState(false);
else {
while (!inputHelper<_BufferSize, _BlockSize>::isEndline(ih.getChar_Checked())) {
ret += ih.getChar_Unchecked();
ih.next();
}
ih.next();
}
return ih;
}
} using OY::getline;
template<__uint128_t __mod, bool __isprime = true>class DynamicModInt {
public:
using u32 = uint64_t;
using i64 = __int128_t;
using u64 = __uint128_t;
using m64 = DynamicModInt;
using value_type = u64;
static inline u64 mod() {
return s_mod;
} static inline u64 get_primitive_root_prime() {
if (!s_isPrime)
return 0;
u64 tmp[500] = {};
u64 cnt = 0;
const u64 phi = s_mod - 1;
u64 m = phi;
for (u64 i = 2; i * i <= m; ++i) {
if (m % i == 0) {
tmp[cnt++] = i;
do
m /= i;
while (m % i == 0)
;
}
}
if (m != 1)
tmp[cnt++] = m;
for (m64 res = 2;; res += 1) {
bool f = true;
for (int i = 0; i < cnt && f; ++i)
f &= res.pow(phi / tmp[i]) != 1;
if (f)
return u64(res);
}
} constexpr DynamicModInt(): v_() {}~DynamicModInt() = default;
template < typename T, typename std::enable_if < std::is_arithmetic<T>::value ||
std::is_same<T, i64>::value ||
std::is_same<T, u64>::value, int >::type = 0 > inline DynamicModInt(T v): v_(reduce(mul(norm(v % i64(s_mod)),
r2))) {} constexpr DynamicModInt(const m64 &) = default;
inline u64 val()const {
return reduce({0, v_});
} template < typename T, typename std::enable_if < std::is_arithmetic<T>::value ||
std::is_same<T, i64>::value ||
std::is_same<T, u64>::value, int >::type = 0 > explicit constexpr operator T()const {
return T(val());
} inline m64 operator-()const {
m64 res;
res.v_ = (s_mod & -(v_ != 0)) - v_;
return res;
} inline m64 inv_exgcd()const {
i64 x1 = 1, x3 = 0, a = val(), b = s_mod;
while (b != 0) {
i64 q = a / b, x1_old = x1, a_old = a;
x1 = x3, x3 = x1_old - x3 * q, a = b, b = a_old - b * q;
}
return m64(x1);
} inline m64 inv_fermat()const {
return pow(s_mod - 2);
} inline m64 inv()const {
return s_isPrime ? inv_fermat() : inv_exgcd();
} inline m64 &operator=(const m64 &) = default;
inline m64 &operator+=(const m64 &rhs) {
v_ += rhs.v_ - s_mod;
v_ += s_mod & -(v_ >> 127);
return*this;
} inline m64 &operator-=(const m64 &rhs) {
v_ -= rhs.v_;
v_ += s_mod & -(v_ >> 127);
return*this;
} inline m64 &operator*=(const m64 &rhs) {
v_ = reduce(mul(v_, rhs.v_));
return*this;
} inline m64 &operator/=(const m64 &rhs) {
return operator*=(rhs.inv());
} friend inline m64 operator+(const m64 &lhs, const m64 &rhs) {
return m64(lhs) += rhs;
} friend inline m64 operator-(const m64 &lhs, const m64 &rhs) {
return m64(lhs) -= rhs;
} friend inline m64 operator*(const m64 &lhs, const m64 &rhs) {
return m64(lhs) *= rhs;
} friend inline m64 operator/(const m64 &lhs, const m64 &rhs) {
return m64(lhs) /= rhs;
} friend inline bool operator==(const m64 &lhs, const m64 &rhs) {
return lhs.v_ == rhs.v_;
} friend inline bool operator!=(const m64 &lhs, const m64 &rhs) {
return lhs.v_ != rhs.v_;
} template<typename _Istream>friend inline _Istream &operator>>(_Istream &is, m64 &rhs) {
i64 x;
is >> x;
rhs = m64(x);
return is;
} template<typename _Ostream>friend _Ostream &operator<<(_Ostream &os, const m64 &rhs) {
return os << rhs.val();
} inline m64 pow(u64 y)const {
m64 res(1), x(*this);
for (; y != 0; y >>= 1, x *= x)
if (y & 1)
res *= x;
return res;
} static inline void set_mod(u64 mod, bool prime = true) {
s_mod = mod;
s_isPrime = prime;
r = get_r();
r2 = get_r2();
} static inline u64 init(u64 val) {
return reduce(mul(val, r2));
} private:
static constexpr std::pair<u64, u64>mul(u64 x, u64 y) {
u64 a = x >> 64, b = u32(x), c = y >> 64, d = u32(y), ad = a * d, bc = b * c;
return{a *c + (ad >> 64) + (bc >> 64) + (((ad & ~UINT64_C(0)) + (bc & ~UINT64_C(0)) + (b * d >> 64)) >> 64), x * y};
} static constexpr u64 mulh(u64 x, u64 y) {
u64 a = x >> 64, b = u32(x), c = y >> 64, d = u32(y), ad = a * d, bc = b * c;
return a * c + (ad >> 64) + (bc >> 64) + (((ad & ~UINT64_C(0)) + (bc & ~UINT64_C(0)) + (b * d >> 64)) >> 64);
} static inline u64 get_r() {
u64 two = 2, iv = s_mod * (two - s_mod * s_mod);
iv *= two - s_mod * iv;
iv *= two - s_mod * iv;
iv *= two - s_mod * iv;
iv *= two - s_mod * iv;
return iv * (two - s_mod * iv);
} static inline u64 get_r2() {
u64 iv = -u64(s_mod) % s_mod;
for (int i = 0; i != 128; ++i)
((iv <<= 1) >= s_mod) && (iv -= s_mod);
return iv;
} static constexpr u64 reduce(const std::pair<u64, u64> &x) {
u64 res = x.first - mulh(x.second * r, s_mod);
return res + (s_mod & -(res >> 127));
} static constexpr u64 norm(i64 x) {
return x + (s_mod & -(x < 0));
} u64 v_;
static inline u64 s_mod = __mod;
static inline u64 s_isPrime = __isprime;
static inline u64 r = get_r();
static inline u64 r2 = get_r2();
};
using mint = DynamicModInt<3, true>;
bool prime(const __uint128_t &x) {
static constexpr __uint128_t first_prime[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
if (x <= 100)
return std::binary_search(first_prime, first_prime + 25, x);
mint::set_mod(x, false);
const mint one(1), none(-1);
__uint128_t y(x - 1);
const unsigned iend = my_countr_zero(y);
y >>= iend;
for (mint base : {
2, 7, 61, 325
}) {
mint z(base.pow(y));
if (z.val() == 1)
continue;
unsigned i = 0;
for (; i ^ iend; i++) {
if (z == none)
break;
z *= z;
}
if (i == iend)
return false;
}
return true;
}
uint64_t seed = 5489ull;
static std::mt19937_64 rng;
__uint128_t gcd(__uint128_t a, __uint128_t b) {
if (!a || !b)
return a | b;
int i = my_countr_zero(a), j = my_countr_zero(b), k = std::min(i, j);
a >>= i;
b >>= j;
while (true) {
if (a < b)
std::swap(a, b);
if (!(a -= b))
break;
a >>= my_countr_zero(a);
}
return b << k;
}
template<typename _Tp>struct Cipolla {
static inline _Tp legrende(unsigned a) {
return _Tp(a).pow((_Tp::mod() - 1) >> 1);
} static inline std::pair<_Tp, _Tp>find_nsqr(unsigned n) {
_Tp none(-1);
for (unsigned i = sqrt(n) + 1e-6 + 1; i < _Tp::mod(); i++)
if (unsigned tmp(i * i - n); legrende(tmp) == none)
return{_Tp(i), _Tp(tmp)};
return none;
} static inline _Tp a, n, c;
static inline void set_nsqr(unsigned n) {
_Tp none(-1);
for (unsigned i = sqrt(n) + 1e-6 + 1; i < _Tp::mod(); i++)
if (unsigned tmp(i * i - n); legrende(tmp) == none) {
a = i;
c = tmp;
return;
}
} struct cp {
_Tp _M_real, _M_imag;
public:
cp(const _Tp &r, const _Tp &i): _M_real(r), _M_imag(i) {} cp(const _Tp &r = _Tp()): _M_real(r),
_M_imag(0) {} cp(const cp &o): _M_real(o._M_real), _M_imag(o._M_imag) {} cp(cp &&o): _M_real(o._M_real),
_M_imag(o._M_imag) {} public:
cp &operator=(const cp &o) {
_M_real = o._M_real;
_M_imag = o._M_imag;
return*this;
} cp &operator=(const _Tp &o) {
_M_real = o;
_M_imag = 0;
return*this;
} public:
~cp() {
_M_real = 0;
_M_imag = 0;
} public:
cp operator+(const cp &o)const {
return cp(_M_real + o._M_real, _M_imag + o._M_imag);
} cp operator*(const cp &o)const {
return cp(_M_real * o._M_real + _M_imag * o._M_imag * c, _M_real * o._M_imag + _M_imag * o._M_real);
} friend cp operator-(const cp &o) {
return cp(-o._M_real, -o._M_imag);
} cp operator-(const cp &o)const {
return*this + -o;
} public:
cp &operator+=(const cp &o) {
return*this = *this + o;
} cp &operator*=(const cp &o) {
return*this = *this * o;
} cp &operator-=(const cp &o) {
return*this = *this - o;
} public:
_Tp &real() {
return _M_real;
} _Tp &imag() {
return _M_imag;
} const _Tp &real()const {
return _M_real;
} const _Tp &imag()const {
return _M_imag;
} cp conj()const {
return cp(_M_real, -_M_imag);
}
};
static cp qpow(const cp &bs, unsigned po) {
cp ans(1, 0), base(bs);
while (po) {
if (po & 1)
ans *= base;
base *= base;
po >>= 1;
}
return ans;
} static inline _Tp get_sqr(const _Tp &nn) {
n = nn;
if (n == _Tp(0))
return _Tp(0);
if (legrende(n.val()) != 1)
return _Tp(-1);
set_nsqr(n.val());
return qpow(cp(a, 1), (_Tp::mod() + 1) >> 1).real();
} static inline _Tp get_sqr_unchecked(const _Tp &nn) {
n = nn;
set_nsqr(n.val());
return qpow(cp(a, 1), (_Tp::mod() + 1) >> 1).real();
}
};
__uint128_t rho(__uint128_t value) {
mint::set_mod(value, false);
mint x, y, z, c;
uint64_t i, j;
while (true) {
y = x = rng();
z = 1;
c = rng();
i = 0;
j = 1;
while (++i) {
y = y * y + c;
z *= (x.val() > y.val()) ? (x - y) : (y - x);
if (x == y || !z.val())
break;
if (!(i & 127) || i == j) {
if (__uint128_t g = gcd(z.val(), value); g > 1)
return g;
if (i == j) {
x = y;
j <<= 1;
}
}
}
}
}
__uint128_t squfof(__uint128_t value) {
__uint128_t s = sqrtl(1.0l * value) + 1e-6;
while (s * s > value)
s--;
if (s * s == value)
return s;
__int128 d, po, p, p_prev, q, q_prev, q_, b, r;
long long l, b_, i;
int k = 0;
l = 2 * sqrtl(2.0l * s);
b_ = 3 * l;
if (b_ > 20000000)
return rho(value);
while (++k) {
d = k * value;
po = p_prev = p = sqrtl(1.0l * d);
q_prev = 1;
q = d - po * po;
while (q < 0) {
po--;
p_prev--;
p--;
q = d - po * po;
}
if (!q)
return gcd(value, k);
for (i = 2; i < b_; i++) {
b = (po + p) / q;
p = b * q - p;
q_ = q;
q = q_prev + b * (p_prev - p);
r = sqrtl(1.0 * q) + 1e-6;
if (!(i & 1) && r * r == q)
break;
q_prev = q_;
p_prev = p;
}
if (i >= b_)
continue;
b = (po - p) / r;
p_prev = p = b * r + p;
q_prev = r;
q = (d - p_prev * p_prev) / q_prev;
i = 0;
do {
b = (po + p) / q;
p_prev = p;
p = b * q - p;
q_ = q;
q = q_prev + b * (p_prev - p);
q_prev = q_;
i++;
} while (p != p_prev && i < b_);
if (i >= b_)
continue;
r = gcd(value, q_prev);
if (r != 1)
return r;
}
return 0;
}
template<typename _ModType>class barrett {
_ModType _M_mod;
int _M_l;
__uint128_t _M_inv;
static constexpr auto _Nd = std::numeric_limits<_ModType>::digits;
static constexpr auto _Nd_ull = std::numeric_limits<uint64_t>::digits;
static constexpr auto _Nd_ul = std::numeric_limits<unsigned long>::digits;
static constexpr auto _Nd_u = std::numeric_limits<unsigned>::digits;
public:
static_assert(std::is_integral<_ModType>::value &&std::is_unsigned<_ModType>::value,
"_ModType must be an unsigned integral type");
constexpr barrett() = default;
constexpr barrett(const _ModType &mod): _M_mod(mod),
_M_l(_Nd_ull + _Nd - __builtin_clzll((uint64_t)mod) - ((mod & (mod - 1)) != 0)),
_M_inv(((unsigned __int128)1 << _M_l) / mod + ((mod & (mod - 1)) != 0)) {} constexpr void set_mod(
const _ModType &mod) {
_M_mod = mod;
_M_l = _Nd_ull + _Nd - __builtin_clzll((uint64_t)mod) - ((mod & (mod - 1)) != 0);
_M_inv = ((unsigned __int128)1 << _M_l) / mod + ((mod & (mod - 1)) != 0);
} constexpr _ModType mod()const {
return _M_mod;
} constexpr _ModType mod(const _ModType &x)const {
__uint128_t tmp = _M_inv * x;
_ModType ret = x - (tmp >> _M_l) * _M_mod;
return ret;
}
};
namespace qs {
const size_t L = 256;
uint32_t pcnt, root[L];
mint primes[L];
double log_primes[L];
struct word {
std::bitset<L>mask;
mint lhs, rhs;
size_t bit;
word(): mask(), lhs(), rhs(), bit(L) {} void merge(const word &rOther) {
lhs *= rOther.lhs;
rhs *= rOther.rhs;
const std::bitset<L>cons(mask & rOther.mask);
for (size_t pos = cons._Find_first(); pos < L; pos = cons._Find_next(pos))
rhs *= primes[pos];
mask ^= rOther.mask;
bit = mask._Find_first();
} bool operator<(const word &rOther)const {
return bit < rOther.bit;
}
};
std::vector<word>smooth;
std::unordered_map<long long, word>data;
__uint128_t insert(word &o) {
size_t x;
for (x = 0; x < smooth.size(); x++) {
if (smooth[x].bit > o.bit)
break;
if (smooth[x].bit == o.bit)
o.merge(smooth[x]);
}
if (o.bit == L) {
__uint128_t g(gcd((o.lhs + o.rhs).val(), mint::mod()));
if (g != 1 && g != mint::mod())
return g;
}
smooth.insert(smooth.begin() + x, o);
return 0;
return 0;
} __int128 try_insert(mint x, __int128 y) {
word ins;
ins.lhs = x;
ins.rhs = 1;
for (size_t k = 1; k <= pcnt; k++) {
size_t cnt = 0;
while (y % (__int128)primes[k].val() == 0)
y /= (__int128)primes[k].val(), ++cnt;
if (cnt) {
ins.mask[k] = cnt & 1;
ins.rhs *= primes[k].pow(cnt >> 1);
}
}
ins.bit = ins.mask._Find_first();
if (y != 1) {
if (data.count(y)) {
ins.merge(data[y]);
ins.rhs *= mint(y);
y = 1;
} else
data[y] = ins;
}
if (y == 1)
return insert(ins);
return 0;
}
void append(uint32_t p) {
++pcnt;
primes[pcnt] = p;
log_primes[pcnt] = log(1.0 * p);
} uint32_t fastpow(__uint128_t base, uint32_t power, uint32_t mod) {
barrett<uint32_t>brt(mod);
base %= mod;
uint32_t ans = 1;
for (; power; base = brt.mod(base * base), power >>= 1)
if (power & 1)
ans = brt.mod(ans * base);
return ans;
} void init() {
using mint_ = DynamicModInt<5, true>;
uint32_t i, j;
__uint128_t value = mint::mod();
uint32_t B = pow(log(1.0 * mint::mod()), 2) * 0.6;
std::vector<char>mark((B >> 1) + 5);
for (i = 3; i * i <= B; i += 2)
if (!mark[i >> 1])
for (j = i * i; j <= B; j += i << 1)
mark[j >> 1] = true;
for (append(2u), i = 3; i <= B; i += 2)
if (!mark[i >> 1])
if (fastpow(value, i >> 1, i) == 1)
append(i);
root[1] = value % 2;
for (i = 2; i <= pcnt; i++)
mint_::set_mod(primes[i].val(), true), root[i] = Cipolla<mint_>::get_sqr(value).val();
} __uint128_t next_prime(__uint128_t x) {
x += ~x & 1;
while (!prime(x += 2))
;
return x;
}
__uint128_t quadratic_sieve(__int128 value) {
if (__int128 tmp = sqrtl(1.0 * value) + 1e-6; tmp * tmp == value)
return tmp;
static constexpr __uint128_t first_prime[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113};
for (int i = 1; i < 30; i++)
if (value % first_prime[i] == 0)
return first_prime[i];
if (value <= 1024)
return squfof(value);
pcnt = 0;
data.clear();
smooth.clear();
mint::set_mod(value, false);
init();
uint32_t M = pcnt * 50;
uint64_t D = sqrtl(sqrtl(2.0L * value) / M);
double bound = log(M * sqrtl(0.5L * value)) * 0.75;
barrett<uint64_t>brt;
while (true) {
do
D = next_prime(D);
while ((D & 3) == 1)
;
mint::set_mod(D, true);
uint64_t y0;
mint y1;
{
mint tmp_value(value);
if (!tmp_value.val())
return D;
mint tmp_y0 = tmp_value.pow((D + 1) >> 2);
if (tmp_y0 * tmp_y0 != tmp_value)
continue;
y0 = tmp_y0.val();
y1 = (value - y0 * y0) / D;
y1 = y1 * (D / 2 + 1) / tmp_y0;
}
__int128 A(D);
A *= A;
__int128 B(y1.val()*D + y0);
__int128 C((B * B - value) / A);
mint::set_mod(value, false);
__int128 E = (mint(B) / D).val();
std::vector<double>pos(M), neg(M);
for (uint32_t x = 1; x <= pcnt; x++) {
uint32_t p = primes[x].val();
brt.set_mod(p);
uint32_t s = brt.mod(A);
uint32_t a = s;
uint32_t inv_a = 1;
if (!a)
continue;
while (a > 1)
inv_a = brt.mod(1ull * (p - inv_a) * (p / a)), a = p % a;
uint32_t u = brt.mod(1ull * (p - brt.mod(B)) * inv_a);
uint32_t v = brt.mod(1ull * root[x] * inv_a);
uint32_t r1 = brt.mod(u + v), r2 = brt.mod(u + p - v);
for (uint32_t su = 0; su < M; su += p) {
if (su + r1 < M)
pos[su + r1] += log_primes[x];
if (su + r2 < M)
pos[su + r2] += log_primes[x];
if (su >= r1)
neg[su - r1] += log_primes[x];
if (su >= r2)
neg[su - r2] += log_primes[x];
}
}
for (uint32_t x = 0; x < M; ++x) {
if (pos[x] > bound)
if (__uint128_t tmp(try_insert(E + D * x, A * x * x + 2 * B * x + C)); tmp)
return tmp;
if (neg[x] > bound)
if (__uint128_t tmp(try_insert(E - D * x, A * x * x - 2 * B * x + C)); tmp)
return tmp;
}
}
return value;
}
}
main() {
OY::inputHelper < 1 << 18, 20 > cin("");
OY::outputHelper < 1 << 18 > cout("");
__uint128_t x = 0;
cin >> x;
__check_time_helper<std::chrono::high_resolution_clock>_Helper;
_Helper.start();
__uint128_t factor = qs::quadratic_sieve(x);
_Helper.stop();
if (factor > x / factor)
factor = x / factor;
cout << factor << ' ' << x / factor;
}
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 4236kb
input:
9866369
output:
113 87313
result:
ok single line: '113 87313'
Test #2:
score: 0
Accepted
time: 1ms
memory: 4544kb
input:
9676411
output:
617 15683
result:
ok single line: '617 15683'
Test #3:
score: 0
Accepted
time: 0ms
memory: 4440kb
input:
9717809
output:
727 13367
result:
ok single line: '727 13367'
Test #4:
score: 0
Accepted
time: 1ms
memory: 4536kb
input:
9957119
output:
829 12011
result:
ok single line: '829 12011'
Test #5:
score: 0
Accepted
time: 1ms
memory: 4548kb
input:
9868337
output:
983 10039
result:
ok single line: '983 10039'
Test #6:
score: 0
Accepted
time: 1ms
memory: 4456kb
input:
9561023
output:
1163 8221
result:
ok single line: '1163 8221'
Test #7:
score: 0
Accepted
time: 0ms
memory: 4368kb
input:
9545761
output:
1367 6983
result:
ok single line: '1367 6983'
Test #8:
score: 0
Accepted
time: 0ms
memory: 4540kb
input:
9607667
output:
1621 5927
result:
ok single line: '1621 5927'
Test #9:
score: 0
Accepted
time: 0ms
memory: 4552kb
input:
9597001
output:
2161 4441
result:
ok single line: '2161 4441'
Test #10:
score: 0
Accepted
time: 1ms
memory: 4548kb
input:
9761267
output:
3023 3229
result:
ok single line: '3023 3229'
Test #11:
score: 0
Accepted
time: 2ms
memory: 4576kb
input:
982258310053
output:
3947 248861999
result:
ok single line: '3947 248861999'
Test #12:
score: 0
Accepted
time: 2ms
memory: 4380kb
input:
951649112653
output:
60727 15670939
result:
ok single line: '60727 15670939'
Test #13:
score: 0
Accepted
time: 1ms
memory: 4520kb
input:
970510479737
output:
82361 11783617
result:
ok single line: '82361 11783617'
Test #14:
score: 0
Accepted
time: 1ms
memory: 4424kb
input:
986989368881
output:
104347 9458723
result:
ok single line: '104347 9458723'
Test #15:
score: 0
Accepted
time: 1ms
memory: 4424kb
input:
957993963593
output:
137957 6944149
result:
ok single line: '137957 6944149'
Test #16:
score: 0
Accepted
time: 2ms
memory: 4424kb
input:
994965772309
output:
189859 5240551
result:
ok single line: '189859 5240551'
Test #17:
score: 0
Accepted
time: 1ms
memory: 4500kb
input:
978534040373
output:
243157 4024289
result:
ok single line: '243157 4024289'
Test #18:
score: 0
Accepted
time: 0ms
memory: 4432kb
input:
971024997479
output:
316531 3067709
result:
ok single line: '316531 3067709'
Test #19:
score: 0
Accepted
time: 0ms
memory: 4536kb
input:
953600891731
output:
550909 1730959
result:
ok single line: '550909 1730959'
Test #20:
score: 0
Accepted
time: 2ms
memory: 4492kb
input:
957601483897
output:
974189 982973
result:
ok single line: '974189 982973'
Test #21:
score: 0
Accepted
time: 2ms
memory: 4516kb
input:
977141658538805467
output:
245593 3978703214419
result:
ok single line: '245593 3978703214419'
Test #22:
score: 0
Accepted
time: 2ms
memory: 4520kb
input:
993640296811069513
output:
15772423 62998582831
result:
ok single line: '15772423 62998582831'
Test #23:
score: 0
Accepted
time: 0ms
memory: 4608kb
input:
972033526800786343
output:
22838183 42561771521
result:
ok single line: '22838183 42561771521'
Test #24:
score: 0
Accepted
time: 2ms
memory: 4432kb
input:
954171962745034819
output:
35159623 27138287653
result:
ok single line: '35159623 27138287653'
Test #25:
score: 0
Accepted
time: 1ms
memory: 4512kb
input:
978341504612724647
output:
52896463 18495404969
result:
ok single line: '52896463 18495404969'
Test #26:
score: 0
Accepted
time: 2ms
memory: 4480kb
input:
964156325695679951
output:
82257599 11721182449
result:
ok single line: '82257599 11721182449'
Test #27:
score: 0
Accepted
time: 2ms
memory: 4580kb
input:
981810768141725077
output:
120632453 8138861009
result:
ok single line: '120632453 8138861009'
Test #28:
score: 0
Accepted
time: 2ms
memory: 4544kb
input:
996600025433706263
output:
188473367 5287749889
result:
ok single line: '188473367 5287749889'
Test #29:
score: 0
Accepted
time: 2ms
memory: 4440kb
input:
953178770133147331
output:
434148317 2195514143
result:
ok single line: '434148317 2195514143'
Test #30:
score: 0
Accepted
time: 2ms
memory: 4468kb
input:
979704186959920183
output:
965382697 1014835039
result:
ok single line: '965382697 1014835039'
Test #31:
score: 0
Accepted
time: 1ms
memory: 4600kb
input:
9681177706327259719477027
output:
30892241 313385413066253747
result:
ok single line: '30892241 313385413066253747'
Test #32:
score: 0
Accepted
time: 4ms
memory: 4520kb
input:
9940536208068119834895493
output:
9801019853 1014234881385881
result:
ok single line: '9801019853 1014234881385881'
Test #33:
score: 0
Accepted
time: 3ms
memory: 4592kb
input:
9997038881982298860346319
output:
17471050273 572205947883503
result:
ok single line: '17471050273 572205947883503'
Test #34:
score: 0
Accepted
time: 4ms
memory: 4688kb
input:
9756859113937123210682929
output:
30453215099 320388473999171
result:
ok single line: '30453215099 320388473999171'
Test #35:
score: 0
Accepted
time: 6ms
memory: 4536kb
input:
9990078255400923282753323
output:
54825911561 182214540004243
result:
ok single line: '54825911561 182214540004243'
Test #36:
score: 0
Accepted
time: 2ms
memory: 4564kb
input:
9883626478214751636971843
output:
99236894717 99596289327679
result:
ok single line: '99236894717 99596289327679'
Test #37:
score: 0
Accepted
time: 5ms
memory: 4524kb
input:
9573361345198621696137959
output:
174744513737 54784903631407
result:
ok single line: '174744513737 54784903631407'
Test #38:
score: 0
Accepted
time: 4ms
memory: 4520kb
input:
9625069927040072137408201
output:
315510198349 30506367075949
result:
ok single line: '315510198349 30506367075949'
Test #39:
score: 0
Accepted
time: 2ms
memory: 4668kb
input:
9558955213557944940797347
output:
961448896637 9942239516831
result:
ok single line: '961448896637 9942239516831'
Test #40:
score: 0
Accepted
time: 5ms
memory: 4608kb
input:
9840941836621191397321379
output:
3053341569527 3223007191477
result:
ok single line: '3053341569527 3223007191477'
Test #41:
score: 0
Accepted
time: 15ms
memory: 4692kb
input:
961656201462920497194293996611
output:
973825889 987503220365627902499
result:
ok single line: '973825889 987503220365627902499'
Test #42:
score: 0
Accepted
time: 8ms
memory: 4644kb
input:
996526819694097128105196470881
output:
994411349447 1002127359314908823
result:
ok single line: '994411349447 1002127359314908823'
Test #43:
score: 0
Accepted
time: 12ms
memory: 4632kb
input:
984638359916649895753226868473
output:
1913886315953 514470661976784841
result:
ok single line: '1913886315953 514470661976784841'
Test #44:
score: 0
Accepted
time: 8ms
memory: 4568kb
input:
954594052218344282851704873817
output:
3979498549097 239877974684763761
result:
ok single line: '3979498549097 239877974684763761'
Test #45:
score: 0
Accepted
time: 19ms
memory: 4756kb
input:
951130323482838313925006521277
output:
7557378146273 125854536464064349
result:
ok single line: '7557378146273 125854536464064349'
Test #46:
score: 0
Accepted
time: 19ms
memory: 4712kb
input:
962697697567853678189739826037
output:
15100422367399 63753031150060163
result:
ok single line: '15100422367399 63753031150060163'
Test #47:
score: 0
Accepted
time: 12ms
memory: 4760kb
input:
956492846963172046572961978627
output:
30582959699219 31275352561367633
result:
ok single line: '30582959699219 31275352561367633'
Test #48:
score: 0
Accepted
time: 12ms
memory: 4612kb
input:
990250331253981534128026179673
output:
61400770095961 16127653280347393
result:
ok single line: '61400770095961 16127653280347393'
Test #49:
score: 0
Accepted
time: 14ms
memory: 4776kb
input:
963782379204510691122291047909
output:
244564652505673 3940808163935933
result:
ok single line: '244564652505673 3940808163935933'
Test #50:
score: 0
Accepted
time: 18ms
memory: 4784kb
input:
955342769363561101863533963531
output:
973806882626147 981039245468473
result:
ok single line: '973806882626147 981039245468473'