/// @title: Count non negative integer tuple (a, b, c) satisfied (sum <= S) and (product <= T)
/// @testing: for large S <= 1e18, T <= 1e12
/// > in O(T^(5/9)) time complexity = 830ms codeforces = 310ms ideone
/// > in O(const) memory complexity
/// > in O(3700Mb) code memory in 200 lines, 4444 characters
///
/// @date: 23/08/2021
/// @link: https://i...content-available-to-author-only...e.com/yMi8tu
/// @author: SPyofgame
/// @lisence: free lisence
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#include <iostream>
#include <cmath>
typedef long long ll;
const int MOD = 1e9 + 7;
///====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====
/// Utility function
ll min(ll a, ll b) { return a < b ? a : b; }
ll max(ll a, ll b) { return a > b ? a : b; }
ll square(ll x) { return x * x; }
/// Sum of (1 + 2 + ... + x)
ll natural_sum(ll x)
{
return (x <= 0) ? 0 : x * (x + 1) / 2;
}
/// Sum of (l + (l + 1) + ... + r)
ll natural_sum(ll l, ll r)
{
return (l > r) ? 0 : natural_sum(r) - natural_sum(l - 1);
}
/// Sigma(p = y -> x) floor(n / p) in O(cbrt(n))
/// @link: https://a...content-available-to-author-only...v.org/pdf/1206.3369.pdf
/// @author: Richard Sladkey
ll fastsumdiv(ll y, ll x, ll n)
{
if (y > x) return 0;
ll S = 0;
ll B = n / (x + 1);
ll E = n % (x + 1);
ll D = n / x - B;
ll G = B - x * D;
ll d = 0;
for (; x >= y; --x)
{
E += G;
if (E >= x)
{
D += 1, G -= x, E -= x;
if (E >= x)
{
D += 1, G -= x, E -= x;
if (E >= x) break; /// not likely to happen more
}
}
else if (E < 0)
{
D -= 1, G += x, E += x;
}
G += 2 * D, B += D, S += B;
}
E = n % (x + 1);
D = n / x - B;
G = B - x * D;
for (; x >= y; --x)
{
E += G;
d = E / x;
D += d;
E -= x * d;
G += 2 * D - x * d, B += D, S += B;
}
for (; x >= y; --x)
{
S += n / x;
}
return S;
}
/// you can modify to -> Bignum / Modulo / Overflow
void add(ll &res, ll val)
{
val %= MOD;
res += val;
if (res >= MOD) res -= MOD;
}
/// you can modify to -> Bignum / Modulo / Overflow
void sub(ll &res, ll val)
{
val %= MOD;
res -= val;
if (res < 0) res += MOD;
}
/// Count (a, b, c) satisfied
/// { min(a, b, c) >= 0
/// { a + b + c <= S
/// { a * b * c <= T
/// > O(T^(5/9)) complexity
///
/// @proof: https://m...content-available-to-author-only...e.com/questions/4230187/faster-algorithm-for-counting-non-negative-tripplea-b-c-satisfied-a-b-c
/// @author: SPyofgame
ll solve_ABC(ll S, ll T)
{
ll cbT = cbrt(T); /// Not very accuracy
while (cbT * cbT * cbT < T) ++cbT;
while (cbT * cbT * cbT > T) --cbT;
/// [1] 0 <= a < b < c && a <= cbrt(T) -> cnt1 * 6
ll cnt1 = 0;
add(cnt1, (S / 2) * S - 2 * natural_sum(S / 2)); /// a = 0
ll k = 1;
for (ll a = 1, upa = min(S, cbT); a <= upa; ++a) /// a > 0 -> count(b < c)
{
ll SSS = S - a;
ll TTT = T / a;
ll KKK = min(SSS / 2, min((ll)sqrt(TTT), TTT / 2 + 1));
/// Binary search for max k satisfy (S - a - k) <= (T / a / k)
ll k = a;
for (ll l = a + 1, r = KKK; l <= r; )
{
ll m = (l + r) >> 1;
ll v = TTT / m;
if (SSS - m <= v)
{
k = m;
l = m + 1;
}
else
{
r = m - 1;
}
}
sub(cnt1, natural_sum(a + 1, KKK));
add(cnt1, SSS * (k - a) - natural_sum(a + 1, k));
add(cnt1, fastsumdiv(k + 1, KKK, TTT));
}
/// [2] 0 <= a < b = c && a <= cbrt(T) -> cnt2 * 3
ll cnt2 = 0;
add(cnt2, S / 2); /// a = 0
for (ll a = 1, upa = min(S, cbT); a <= upa; ++a) /// a > 0 -> count(b = c)
{
add(cnt2, max(0LL, min((S - a) / 2, ll(floor(sqrt(T / a)))) - a));
}
/// [3] 0 <= a = b < c && a <= cbrt(T) -> cnt3 * 3
ll cnt3 = 0;
add(cnt3, S); /// a = 0
for (ll a = 1, upa = min(S / 2, cbT); a <= upa; ++a) /// a > 0 -> count(a < c)
{
add(cnt3, max(0LL, min(S - a - a, T / a / a) - a));
}
/// [4] 0 <= a = b = c && a <= cbrt(T) -> cnt4 * 1
ll cnt4 = 0;
add(cnt4, min(S / 3, cbT) + 1); /// a = b = c >= 0
/// Final result: total counting
ll res = 0;
add(res, cnt1 * 6 + cnt2 * 3 + cnt3 * 3 + cnt4 * 1);
return res;
}
/// Main function
int main()
{
/// Input any number 0 <= S, T <= 1e18
std::cout << solve_ABC(1000000000000000000LL, 1000000000000LL);
return 0;
}
Ly8vIEB0aXRsZTogQ291bnQgbm9uIG5lZ2F0aXZlIGludGVnZXIgdHVwbGUgKGEsIGIsIGMpIHNhdGlzZmllZCAoc3VtIDw9IFMpIGFuZCAocHJvZHVjdCA8PSBUKQovLy8gQHRlc3Rpbmc6IGZvciBsYXJnZSBTIDw9IDFlMTgsIFQgPD0gMWUxMgovLy8gPiBpbiBPKFReKDUvOSkpIHRpbWUgY29tcGxleGl0eSA9IDgzMG1zIGNvZGVmb3JjZXMgPSAzMTBtcyBpZGVvbmUKLy8vID4gaW4gTyhjb25zdCkgbWVtb3J5IGNvbXBsZXhpdHkKLy8vID4gaW4gTygzNzAwTWIpIGNvZGUgbWVtb3J5IGluIDIwMCBsaW5lcywgNDQ0NCBjaGFyYWN0ZXJzCi8vLwovLy8gQGRhdGU6ICAgIDIzLzA4LzIwMjEKLy8vIEBsaW5rOiAgICBodHRwczovL2kuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmUuY29tL3lNaTh0dQovLy8gQGF1dGhvcjogIFNQeW9mZ2FtZQovLy8gQGxpc2VuY2U6IGZyZWUgbGlzZW5jZQoKI3ByYWdtYSBHQ0MgdGFyZ2V0ICgiYXZ4MiIpCiNwcmFnbWEgR0NDIG9wdGltaXphdGlvbiAoIk8zIikKI3ByYWdtYSBHQ0Mgb3B0aW1pemF0aW9uICgidW5yb2xsLWxvb3BzIikKCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGNtYXRoPgoKdHlwZWRlZiBsb25nIGxvbmcgbGw7CmNvbnN0IGludCBNT0QgPSAxZTkgKyA3OwoKLy8vPT09PSo9PT09Kj09PT0qPT09PSo9PT09Kj09PT0qPT09PSo9PT09Kj09PT0qPT09PSo9PT09Kj09PT0qPT09PSo9PT09Kj09PT0qPT09PSo9PT09Kj09PT0qPT09PSo9PT09CgovLy8gVXRpbGl0eSBmdW5jdGlvbgpsbCBtaW4obGwgYSwgbGwgYikgeyByZXR1cm4gYSA8IGIgPyBhIDogYjsgfQpsbCBtYXgobGwgYSwgbGwgYikgeyByZXR1cm4gYSA+IGIgPyBhIDogYjsgfQpsbCBzcXVhcmUobGwgeCkgeyByZXR1cm4geCAqIHg7IH0KCi8vLyBTdW0gb2YgKDEgKyAyICsgLi4uICsgeCkKbGwgbmF0dXJhbF9zdW0obGwgeCkKewogICAgcmV0dXJuICh4IDw9IDApID8gMCA6IHggKiAoeCArIDEpIC8gMjsKfQoKLy8vIFN1bSBvZiAobCArIChsICsgMSkgKyAuLi4gKyByKQpsbCBuYXR1cmFsX3N1bShsbCBsLCBsbCByKQp7CiAgICByZXR1cm4gKGwgPiByKSA/IDAgOiBuYXR1cmFsX3N1bShyKSAtIG5hdHVyYWxfc3VtKGwgLSAxKTsKfQoKLy8vIFNpZ21hKHAgPSB5IC0+IHgpIGZsb29yKG4gLyBwKSBpbiBPKGNicnQobikpCi8vLyBAbGluazogaHR0cHM6Ly9hLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi52Lm9yZy9wZGYvMTIwNi4zMzY5LnBkZgovLy8gQGF1dGhvcjogUmljaGFyZCBTbGFka2V5CmxsIGZhc3RzdW1kaXYobGwgeSwgbGwgeCwgbGwgbikKewogICAgaWYgKHkgPiB4KSByZXR1cm4gMDsKCiAgICBsbCBTID0gMDsKICAgIGxsIEIgPSBuIC8gKHggKyAxKTsKICAgIGxsIEUgPSBuICUgKHggKyAxKTsKICAgIGxsIEQgPSBuIC8geCAtIEI7CiAgICBsbCBHID0gQiAtIHggKiBEOwogICAgbGwgZCA9IDA7CgogICAgZm9yICg7IHggPj0geTsgLS14KQogICAgewogICAgICAgIEUgKz0gRzsKICAgICAgICBpZiAoRSA+PSB4KQogICAgICAgIHsKICAgICAgICAgICAgRCArPSAxLCBHIC09IHgsIEUgLT0geDsKICAgICAgICAgICAgaWYgKEUgPj0geCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgRCArPSAxLCBHIC09IHgsIEUgLT0geDsKICAgICAgICAgICAgICAgIGlmIChFID49IHgpIGJyZWFrOyAvLy8gbm90IGxpa2VseSB0byBoYXBwZW4gbW9yZQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKEUgPCAwKQogICAgICAgIHsKICAgICAgICAgICAgRCAtPSAxLCBHICs9IHgsIEUgKz0geDsKICAgICAgICB9CgogICAgICAgIEcgKz0gMiAqIEQsIEIgKz0gRCwgUyArPSBCOwogICAgfQoKICAgIEUgPSBuICUgKHggKyAxKTsKICAgIEQgPSBuIC8geCAtIEI7CiAgICBHID0gQiAtIHggKiBEOwogICAgZm9yICg7IHggPj0geTsgLS14KQogICAgewogICAgICAgIEUgKz0gRzsKICAgICAgICBkID0gRSAvIHg7CiAgICAgICAgRCArPSBkOwogICAgICAgIEUgLT0geCAqIGQ7CiAgICAgICAgRyArPSAyICogRCAtIHggKiBkLCBCICs9IEQsIFMgKz0gQjsKICAgIH0KCiAgICBmb3IgKDsgeCA+PSB5OyAtLXgpCiAgICB7CiAgICAgICAgUyArPSBuIC8geDsKICAgIH0KCiAgICByZXR1cm4gUzsKfQoKLy8vIHlvdSBjYW4gbW9kaWZ5IHRvIC0+IEJpZ251bSAvIE1vZHVsbyAvIE92ZXJmbG93CnZvaWQgYWRkKGxsICZyZXMsIGxsIHZhbCkKewogICAgdmFsICU9IE1PRDsKICAgIHJlcyArPSB2YWw7CiAgICBpZiAocmVzID49IE1PRCkgcmVzIC09IE1PRDsKfQoKLy8vIHlvdSBjYW4gbW9kaWZ5IHRvIC0+IEJpZ251bSAvIE1vZHVsbyAvIE92ZXJmbG93CnZvaWQgc3ViKGxsICZyZXMsIGxsIHZhbCkKewogICAgdmFsICU9IE1PRDsKICAgIHJlcyAtPSB2YWw7CiAgICBpZiAocmVzIDwgMCkgcmVzICs9IE1PRDsKfQoKLy8vIENvdW50IChhLCBiLCBjKSBzYXRpc2ZpZWQKLy8vIHsgbWluKGEsIGIsIGMpID49IDAKLy8vIHsgYSArIGIgKyBjIDw9IFMKLy8vIHsgYSAqIGIgKiBjIDw9IFQKLy8vID4gTyhUXig1LzkpKSBjb21wbGV4aXR5Ci8vLwovLy8gQHByb29mOiBodHRwczovL20uLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmUuY29tL3F1ZXN0aW9ucy80MjMwMTg3L2Zhc3Rlci1hbGdvcml0aG0tZm9yLWNvdW50aW5nLW5vbi1uZWdhdGl2ZS10cmlwcGxlYS1iLWMtc2F0aXNmaWVkLWEtYi1jCi8vLyBAYXV0aG9yOiBTUHlvZmdhbWUKbGwgc29sdmVfQUJDKGxsIFMsIGxsIFQpCnsKICAgIGxsIGNiVCA9IGNicnQoVCk7IC8vLyBOb3QgdmVyeSBhY2N1cmFjeQogICAgd2hpbGUgKGNiVCAqIGNiVCAqIGNiVCA8IFQpICsrY2JUOwogICAgd2hpbGUgKGNiVCAqIGNiVCAqIGNiVCA+IFQpIC0tY2JUOwoKCgovLy8gWzFdIDAgPD0gYSA8IGIgPCBjICYmIGEgPD0gY2JydChUKSAtPiBjbnQxICogNgogICAgbGwgY250MSA9IDA7CiAgICBhZGQoY250MSwgKFMgLyAyKSAqIFMgLSAyICogbmF0dXJhbF9zdW0oUyAvIDIpKTsgLy8vIGEgPSAwCgogICAgbGwgayA9IDE7CiAgICBmb3IgKGxsIGEgPSAxLCB1cGEgPSBtaW4oUywgY2JUKTsgYSA8PSB1cGE7ICsrYSkgLy8vIGEgPiAwIC0+IGNvdW50KGIgPCBjKQogICAgewogICAgICAgIGxsIFNTUyA9IFMgLSBhOwogICAgICAgIGxsIFRUVCA9IFQgLyBhOwogICAgICAgIGxsIEtLSyA9IG1pbihTU1MgLyAyLCBtaW4oKGxsKXNxcnQoVFRUKSwgVFRUIC8gMiArIDEpKTsKCiAgICAgICAgLy8vIEJpbmFyeSBzZWFyY2ggZm9yIG1heCBrIHNhdGlzZnkgKFMgLSBhIC0gaykgPD0gKFQgLyBhIC8gaykKICAgICAgICBsbCBrID0gYTsKICAgICAgICBmb3IgKGxsIGwgPSBhICsgMSwgciA9IEtLSzsgbCA8PSByOyApCiAgICAgICAgewogICAgICAgICAgICBsbCBtID0gKGwgKyByKSA+PiAxOwogICAgICAgICAgICBsbCB2ID0gVFRUIC8gbTsKICAgICAgICAgICAgaWYgKFNTUyAtIG0gPD0gdikKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgayA9IG07CiAgICAgICAgICAgICAgICBsID0gbSArIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByID0gbSAtIDE7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHN1YihjbnQxLCBuYXR1cmFsX3N1bShhICsgMSwgS0tLKSk7CiAgICAgICAgYWRkKGNudDEsIFNTUyAqIChrIC0gYSkgLSBuYXR1cmFsX3N1bShhICsgMSwgaykpOwogICAgICAgIGFkZChjbnQxLCBmYXN0c3VtZGl2KGsgKyAxLCBLS0ssIFRUVCkpOwogICAgfQoKCgovLy8gWzJdIDAgPD0gYSA8IGIgPSBjICYmIGEgPD0gY2JydChUKSAtPiBjbnQyICogMwogICAgbGwgY250MiA9IDA7CiAgICBhZGQoY250MiwgUyAvIDIpOyAvLy8gYSA9IDAKICAgIGZvciAobGwgYSA9IDEsIHVwYSA9IG1pbihTLCBjYlQpOyBhIDw9IHVwYTsgKythKSAvLy8gYSA+IDAgLT4gY291bnQoYiA9IGMpCiAgICB7CiAgICAgICAgYWRkKGNudDIsIG1heCgwTEwsIG1pbigoUyAtIGEpIC8gMiwgbGwoZmxvb3Ioc3FydChUIC8gYSkpKSkgLSBhKSk7CiAgICB9CgoKCi8vLyBbM10gMCA8PSBhID0gYiA8IGMgJiYgYSA8PSBjYnJ0KFQpIC0+IGNudDMgKiAzCiAgICBsbCBjbnQzID0gMDsKICAgIGFkZChjbnQzLCBTKTsgLy8vIGEgPSAwCiAgICBmb3IgKGxsIGEgPSAxLCB1cGEgPSBtaW4oUyAvIDIsIGNiVCk7IGEgPD0gdXBhOyArK2EpIC8vLyBhID4gMCAtPiBjb3VudChhIDwgYykKICAgIHsKICAgICAgICBhZGQoY250MywgbWF4KDBMTCwgbWluKFMgLSBhIC0gYSwgVCAvIGEgLyBhKSAtIGEpKTsKICAgIH0KCgoKLy8vIFs0XSAwIDw9IGEgPSBiID0gYyAmJiBhIDw9IGNicnQoVCkgLT4gY250NCAqIDEKICAgIGxsIGNudDQgPSAwOwogICAgYWRkKGNudDQsIG1pbihTIC8gMywgY2JUKSArIDEpOyAvLy8gYSA9IGIgPSBjID49IDAKCgoKLy8vIEZpbmFsIHJlc3VsdDogdG90YWwgY291bnRpbmcKICAgIGxsIHJlcyA9IDA7CiAgICBhZGQocmVzLCBjbnQxICogNiArIGNudDIgKiAzICsgY250MyAqIDMgKyBjbnQ0ICogMSk7CiAgICByZXR1cm4gcmVzOwp9CgovLy8gTWFpbiBmdW5jdGlvbgppbnQgbWFpbigpCnsKCS8vLyBJbnB1dCBhbnkgbnVtYmVyIDAgPD0gUywgVCA8PSAxZTE4CiAgICBzdGQ6OmNvdXQgPDwgc29sdmVfQUJDKDEwMDAwMDAwMDAwMDAwMDAwMDBMTCwgMTAwMDAwMDAwMDAwMExMKTsKICAgIHJldHVybiAwOwp9Cg==