#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using Int = long long; template ostream &operator<<(ostream &os, const pair &a) { return os << "(" << a.first << ", " << a.second << ")"; }; template void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; } template bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; } template bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; } template vector merge(const vector &a, const vector &b) { vector c(a.size() + b.size()); std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); return c; } template T power(T a, Int e, T m) { T b = 1; for (; e; e >>= 1) { if (e & 1) b = (b * a) % m; a = (a * a) % m; } return b; } Int gcd(Int a, Int b) { if (a < 0) a = -a; if (b < 0) b = -b; if (a == 0) return b; if (b == 0) return a; const int s = __builtin_ctzll(a | b); a >>= __builtin_ctzll(a); do { b >>= __builtin_ctzll(b); if (a > b) std::swap(a, b); b -= a; } while (b); return a << s; } // Checks if n is a prime using Miller-Rabin test bool isPrime(Int n) { if (n <= 1 || n % 2 == 0) return (n == 2); const int s = __builtin_ctzll(n - 1); const Int d = (n - 1) >> s; // http://miller-rabin.appspot.com/ for (const Int base : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) { __int128_t a = base % n; if (a == 0) continue; a = power<__int128_t>(a, d, n); if (a == 1 || a == n - 1) continue; bool ok = false; for (int i = 0; i < s - 1; ++i) { a = (a * a) % n; if (a == n - 1) { ok = true; break; } } if (!ok) return false; } return true; } // Factorize n using Pollard's rho algorithm vector factorize(Int n) { if (n <= 1) return {}; if (isPrime(n)) return {n}; if (n % 2 == 0) return merge({2}, factorize(n / 2)); for (Int c = 1; ; ++c) { Int x = 2, y = 2, d; do { x = (static_cast<__int128_t>(x) * x + c) % n; y = (static_cast<__int128_t>(y) * y + c) % n; y = (static_cast<__int128_t>(y) * y + c) % n; d = gcd(x - y, n); } while (d == 1); if (d < n) return merge(factorize(d), factorize(n / d)); } } int psLen; vector ps, ds; void dfs(int pos, Int d, bool skipped) { if (pos == psLen) { ds.push_back(d); } else { dfs(pos + 1, d, true); if (!skipped || ps[pos - 1] < ps[pos]) { dfs(pos + 1, d * ps[pos], false); } } } vector getDivisors(Int n) { ps = factorize(n); psLen = ps.size(); ds.clear(); dfs(0, 1, false); cerr<<"getDivisors "< Y) { swap(X, Y); } Int ans = 0; if (X == Y) { // B = C auto check0 = [&](Int d) { if (d > 1) { ++ans; } }; const auto ds = getDivisors(X); for (const Int d : ds) { check0(d); } // A = 1, B != C ans += (X - 1) / 2 * 2; } else { auto check = [&](Int d) { const Int a = d + 1; const Int denom = a * a - 1; const Int numerB = a * X - Y; const Int numerC = a * Y - X; if (numerB > 0 && numerC > 0 && numerB % denom == 0 && numerC % denom == 0) { ++ans; } }; const auto ds = getDivisors(Y - X); for (const Int d : ds) { check(d); } } printf("%lld\n", ans); } } return 0; }