QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#811254#998. 素数分解kzoacnAC ✓47ms4256kbC++148.6kb2024-12-12 17:01:372024-12-12 17:01:37

Judging History

This is the latest submission verdict.

  • [2024-12-12 17:01:37]
  • Judged
  • Verdict: AC
  • Time: 47ms
  • Memory: 4256kb
  • [2024-12-12 17:01:37]
  • Submitted

answer

#pragma GCC optimize(2)
#include <bits/stdc++.h>

using namespace std;

using f64 = double;
using f128 = __float128;
using i64 = long long;
using i128 = __int128;
using u64 = unsigned long long;
using u128 = __uint128_t;

template <class T>
void read(T &x) {
    char c;

    for (c = getchar(); c < '0' || c > '9'; c = getchar())
        ;

    for (x = 0; c <= '9' && c >= '0'; c = getchar())
        x = x * 10 + (c & 15);
}
template <class I>
string to_str(I x) {
    if (!x)
        return "0";

    if (x < 0)
        return "-" + to_str(-x);

    string res = "";

    while (x)
        res += x % 10 + '0', x /= 10;

    reverse(res.begin(), res.end());
    return res;
}
ostream &operator<<(ostream &cout, i128 x) {
    return (cout << to_str(x));
}
ostream &operator<<(ostream &cout, u128 x) {
    return (cout << to_str(x));
}

namespace Solver {

u64 pow_64(u64 a, u64 t, u64 mod) {
    u64 r = 1;

    for (; t; t >>= 1, a = u128(a) * a % mod)
        if (t & 1)
            r = u128(r) * a % mod;

    return r;
}
bool check_prime(u64 n) {
    static const int jp[] = { 2, 3, 5, 7, 11, 13, 17, 19 };

    if (n == 1)
        return false;

    for (int p : jp)
        if (n % p == 0)
            return n == p;

    u64 r = n - 1, x, y;
    int e = 0;

    while (~r & 1)
        r >>= 1, ++e;

    for (int p : jp) {
        x = pow_64(p, r, n);

        for (int t = 0; t < e && x > 1; ++t) {
            y = (i128)x * x % n;

            if (y == 1 && x != n - 1)
                return false;

            x = y;
        }

        if (x != 1)
            return false;
    }

    return true;
}
u64 next_prime(u64 n) {
    n += ~n & 1;

    while (!check_prime(n += 2))
        ;

    return n;
}

u128 ctz(u128 x) {
    return u64(x) ? __builtin_ctzll(x) : __builtin_ctzll(x >> 64) + 64;
}
u128 gcd(u128 a, u128 b) {
    if (!a || !b)
        return a | b;

    int shift = ctz(a | b);

    for (b >>= ctz(b); a; a -= b)
        if ((a >>= ctz(a)) < b)
            swap(a, b);

    return b << shift;
}


// sqrt of u128 x, by binary search

u128 isqrt(u128 x){
    u128 l = 0, r = ULLONG_MAX;
    while(l<r){
        u128 mid = (l+r+1)>>1;
        if(mid*mid <= x){
            l = mid;
        }else{
            r = mid-1;
        }
    }
    return l;
}


struct u256 {
    u128 lo, hi;
    u256() {}
    u256(u128 lo, u128 hi) : lo(lo), hi(hi) {}
    static u256 mul128(u128 a, u128 b) {
        u64 a_hi = a >> 64, a_lo = u64(a);
        u64 b_hi = b >> 64, b_lo = u64(b);
        u128 p01 = u128(a_lo) * b_lo;
        u128 p12 = u128(a_hi) * b_lo + u64(p01 >> 64);
        u64 t_hi = p12 >> 64, t_lo = p12;
        p12 = u128(a_lo) * b_hi + t_lo;
        u128 p23 = u128(a_hi) * b_hi + u64(p12 >> 64) + t_hi;
        return u256(u64(p01) | (p12 << 64), p23);
    }
};

struct Mont {
    u128 mod, inv, r2;
    Mont(u128 n) : mod(n) {
        assert(n & 1);
        inv = n;

        for (int i = 0; i < 6; ++i)
            inv *= 2 - n * inv;

        r2 = -n % n;

        for (int i = 0; i < 4; ++i)
            if ((r2 <<= 1) >= mod)
                r2 -= mod;

        for (int i = 0; i < 5; ++i)
            r2 = mul(r2, r2);
    }
    u128 reduce(u256 x) const {
        u128 y = x.hi - u256::mul128(x.lo * inv, mod).hi;
        return i128(y) < 0 ? y + mod : y;
    }
    u128 reduce(u128 x) const {
        return reduce(u256(x, 0));
    }
    u128 init(u128 n) const {
        return reduce(u256::mul128(n, r2));
    }
    u128 mul(u128 a, u128 b) const {
        return reduce(u256::mul128(a, b));
    }
} mont(1);

i128 N;
i128 add(i128 a, i128 b) {
    return (a += b) <= N ? a : a - N;
}
i128 sub(i128 a, i128 b) {
    return (a -= b) < 0 ? a + N : a;
}
i128 mul(i128 a, i128 b) {
    return mont.mul(a, b);
}
void exgcd(i128 a, i128 b, i128 &x, i128 &y) {
    if (b == 0)
        return (void)(x = 1, y = 0);

    exgcd(b, a % b, y, x), y -= a / b * x;
}
i128 inv128(i128 t) {
    i128 q = N, x, y;
    exgcd(t, q, x, y);
    return (x % N + N) % N;
}

inline void _print(u128 x){
    if(x == 0)return;
    _print(x/10);
    putchar(x%10+'0');
}

void print(u128 x){
    _print(x);
    puts("");
}


const int L = 250;
int prime[L], pcnt, root[L];
u128 _mont_prime[L];
f64 logp[L];

struct word {
    bitset<L> mask;
    u128 lhs, rhs;
    int bit;
    word() {
        mask = lhs = rhs = 0, bit = L;
    }
    void merge(word &x) {
        lhs = mul(lhs, x.lhs), rhs = mul(rhs, x.rhs);
        bitset<L> cons = mask & x.mask;

        for (int pos = cons._Find_first(); pos < L; pos = cons._Find_next(pos))
            rhs = mul(rhs, _mont_prime[pos]);

        mask ^= x.mask, bit = mask._Find_first();
    }
};
vector<word> smooth;
unordered_map<i64, word> data;
void insert(word &o) {
    int 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) {
        u128 g = gcd(o.lhs + o.rhs, N);

        if (g != 1 && g != N) {
            if (g > N / g)
                g = N / g;

            cout << g << ' ' << N / g << endl;
            cerr << clock() << endl;
            exit(0);
        }
    } else
        smooth.insert(smooth.begin() + x, o);
}
void try_insert(i128 x, i128 y) {
    while (x < 0)
        x += N;

    word ins;
    ins.lhs = x, ins.rhs = 1;

    for (int k = 1; k <= pcnt; ++k) {
        int cnt = 0;

        while (y % prime[k] == 0)
            y /= prime[k], ++cnt;

        if (cnt)
            for (ins.mask[k] = cnt & 1, cnt >>= 1; cnt; --cnt)
                ins.rhs *= prime[k];
    }

    ins.lhs = mont.init(ins.lhs % N);
    ins.rhs = mont.init(ins.rhs % N);
    ins.bit = ins.mask._Find_first();

    if (y != 1) {
        u128 sqrt_y = isqrt(y);
        
        //print(sqrt_y);
        //print(y);
        //puts("---------");

        if(mul(sqrt_y, sqrt_y) == y){
            ins.rhs = mul(ins.rhs, mont.init(sqrt_y));
            y = 1;
            puts("got");
            exit(0);
            //cerr << "find sqrt" << endl;
        }
    }

    if (y == 1)
        insert(ins);
}
void init() {
    int i, j;
    int B = pow(log(1. * N), 2) * .6;
    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;

    auto append = [&](int p) {
        prime[++pcnt] = p, _mont_prime[pcnt] = mont.init(p), logp[pcnt] = log(p);
    };

    for (append(2), i = 3; i <= B; i += 2)
        if (!mark[i >> 1])
            if (pow_64(N % i, i >> 1, i) == 1)
                append(i);

    for (i = 1; i <= pcnt; ++i)
        for (j = N % prime[i]; root[i] * root[i] % prime[i] != j; ++root[i])
            ;
}
void main() {
    read(N);
    mont = Mont(N);
    init();
    int M = pcnt * 50;
    i64 D = sqrt(sqrt(2. * N) / M);
    f64 bound = log(M * sqrt(.5 * N)) * 0.75;

    while (true) {
        do
            D = next_prime(D);

        while ((D & 3) == 1);

        u64 y0 = pow_64(u64(N % D), (D + 1) >> 2, D);

        if ((i128(y0) * y0 - N) % D)
            continue;

        u64 y1 = u64((N - y0 * y0) / D % D + D) % D;
        y1 = u128(y1) * (D / 2 + 1) % D * pow_64(y0, D - 2, D) % D;
        i128 A = i128(D) * D;
        i128 B = u128(y1) * D + y0;
        i128 C = (B * B - N) / A;
        i128 E = mul(mont.init(B), inv128(D));
        vector<f64> pos(M), neg(M);

        for (int x = 1; x <= pcnt; ++x) {
            int p = prime[x], s = A % p, a = A % p, inv_a = 1;

            if (!a)
                continue;

            while (a > 1)
                inv_a = (p - inv_a) * (p / a) % p, a = p % a;

            int u = (p - B % p) * inv_a % p, v = root[x] * inv_a % p;
            int r1 = (u + v) % p, r2 = (u - v + p) % p;

            for (int su = 0; su < M; su += p) {
                if (su + r1 < M)
                    pos[su + r1] += logp[x];

                if (su + r2 < M)
                    pos[su + r2] += logp[x];

                if (su > 0)
                    neg[su - r1] += logp[x], neg[su - r2] += logp[x];
            }
        }

        for (int x = 0; x < M; ++x) {
            if (pos[x] > bound)
                try_insert(E + D * x, A * x * x + 2 * B * x + C);

            if (neg[x] > bound)
                try_insert(E - D * x, A * x * x - 2 * B * x + C);
        }
    }
}

}
int main() {
    Solver::main();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 4048kb

input:

9866369

output:

113 87313

result:

ok single line: '113 87313'

Test #2:

score: 0
Accepted
time: 0ms
memory: 4056kb

input:

9676411

output:

617 15683

result:

ok single line: '617 15683'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3808kb

input:

9717809

output:

727 13367

result:

ok single line: '727 13367'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3908kb

input:

9957119

output:

829 12011

result:

ok single line: '829 12011'

Test #5:

score: 0
Accepted
time: 1ms
memory: 4040kb

input:

9868337

output:

983 10039

result:

ok single line: '983 10039'

Test #6:

score: 0
Accepted
time: 0ms
memory: 4056kb

input:

9561023

output:

1163 8221

result:

ok single line: '1163 8221'

Test #7:

score: 0
Accepted
time: 0ms
memory: 3796kb

input:

9545761

output:

1367 6983

result:

ok single line: '1367 6983'

Test #8:

score: 0
Accepted
time: 0ms
memory: 3904kb

input:

9607667

output:

1621 5927

result:

ok single line: '1621 5927'

Test #9:

score: 0
Accepted
time: 0ms
memory: 3812kb

input:

9597001

output:

2161 4441

result:

ok single line: '2161 4441'

Test #10:

score: 0
Accepted
time: 0ms
memory: 3840kb

input:

9761267

output:

3023 3229

result:

ok single line: '3023 3229'

Test #11:

score: 0
Accepted
time: 1ms
memory: 3928kb

input:

982258310053

output:

3947 248861999

result:

ok single line: '3947 248861999'

Test #12:

score: 0
Accepted
time: 1ms
memory: 4076kb

input:

951649112653

output:

60727 15670939

result:

ok single line: '60727 15670939'

Test #13:

score: 0
Accepted
time: 1ms
memory: 3916kb

input:

970510479737

output:

82361 11783617

result:

ok single line: '82361 11783617'

Test #14:

score: 0
Accepted
time: 0ms
memory: 3928kb

input:

986989368881

output:

104347 9458723

result:

ok single line: '104347 9458723'

Test #15:

score: 0
Accepted
time: 0ms
memory: 3860kb

input:

957993963593

output:

137957 6944149

result:

ok single line: '137957 6944149'

Test #16:

score: 0
Accepted
time: 0ms
memory: 3924kb

input:

994965772309

output:

189859 5240551

result:

ok single line: '189859 5240551'

Test #17:

score: 0
Accepted
time: 0ms
memory: 3808kb

input:

978534040373

output:

243157 4024289

result:

ok single line: '243157 4024289'

Test #18:

score: 0
Accepted
time: 1ms
memory: 4008kb

input:

971024997479

output:

316531 3067709

result:

ok single line: '316531 3067709'

Test #19:

score: 0
Accepted
time: 0ms
memory: 3928kb

input:

953600891731

output:

550909 1730959

result:

ok single line: '550909 1730959'

Test #20:

score: 0
Accepted
time: 1ms
memory: 3952kb

input:

957601483897

output:

974189 982973

result:

ok single line: '974189 982973'

Test #21:

score: 0
Accepted
time: 1ms
memory: 4036kb

input:

977141658538805467

output:

245593 3978703214419

result:

ok single line: '245593 3978703214419'

Test #22:

score: 0
Accepted
time: 1ms
memory: 3860kb

input:

993640296811069513

output:

15772423 62998582831

result:

ok single line: '15772423 62998582831'

Test #23:

score: 0
Accepted
time: 1ms
memory: 3880kb

input:

972033526800786343

output:

22838183 42561771521

result:

ok single line: '22838183 42561771521'

Test #24:

score: 0
Accepted
time: 1ms
memory: 3972kb

input:

954171962745034819

output:

35159623 27138287653

result:

ok single line: '35159623 27138287653'

Test #25:

score: 0
Accepted
time: 1ms
memory: 3968kb

input:

978341504612724647

output:

52896463 18495404969

result:

ok single line: '52896463 18495404969'

Test #26:

score: 0
Accepted
time: 1ms
memory: 3968kb

input:

964156325695679951

output:

82257599 11721182449

result:

ok single line: '82257599 11721182449'

Test #27:

score: 0
Accepted
time: 1ms
memory: 3988kb

input:

981810768141725077

output:

120632453 8138861009

result:

ok single line: '120632453 8138861009'

Test #28:

score: 0
Accepted
time: 1ms
memory: 3932kb

input:

996600025433706263

output:

188473367 5287749889

result:

ok single line: '188473367 5287749889'

Test #29:

score: 0
Accepted
time: 1ms
memory: 4120kb

input:

953178770133147331

output:

434148317 2195514143

result:

ok single line: '434148317 2195514143'

Test #30:

score: 0
Accepted
time: 0ms
memory: 4116kb

input:

979704186959920183

output:

965382697 1014835039

result:

ok single line: '965382697 1014835039'

Test #31:

score: 0
Accepted
time: 5ms
memory: 4040kb

input:

9681177706327259719477027

output:

30892241 313385413066253747

result:

ok single line: '30892241 313385413066253747'

Test #32:

score: 0
Accepted
time: 5ms
memory: 4108kb

input:

9940536208068119834895493

output:

9801019853 1014234881385881

result:

ok single line: '9801019853 1014234881385881'

Test #33:

score: 0
Accepted
time: 8ms
memory: 4000kb

input:

9997038881982298860346319

output:

17471050273 572205947883503

result:

ok single line: '17471050273 572205947883503'

Test #34:

score: 0
Accepted
time: 3ms
memory: 4188kb

input:

9756859113937123210682929

output:

30453215099 320388473999171

result:

ok single line: '30453215099 320388473999171'

Test #35:

score: 0
Accepted
time: 8ms
memory: 4256kb

input:

9990078255400923282753323

output:

54825911561 182214540004243

result:

ok single line: '54825911561 182214540004243'

Test #36:

score: 0
Accepted
time: 7ms
memory: 4056kb

input:

9883626478214751636971843

output:

99236894717 99596289327679

result:

ok single line: '99236894717 99596289327679'

Test #37:

score: 0
Accepted
time: 7ms
memory: 3948kb

input:

9573361345198621696137959

output:

174744513737 54784903631407

result:

ok single line: '174744513737 54784903631407'

Test #38:

score: 0
Accepted
time: 4ms
memory: 3880kb

input:

9625069927040072137408201

output:

315510198349 30506367075949

result:

ok single line: '315510198349 30506367075949'

Test #39:

score: 0
Accepted
time: 5ms
memory: 4060kb

input:

9558955213557944940797347

output:

961448896637 9942239516831

result:

ok single line: '961448896637 9942239516831'

Test #40:

score: 0
Accepted
time: 6ms
memory: 4004kb

input:

9840941836621191397321379

output:

3053341569527 3223007191477

result:

ok single line: '3053341569527 3223007191477'

Test #41:

score: 0
Accepted
time: 31ms
memory: 4244kb

input:

961656201462920497194293996611

output:

973825889 987503220365627902499

result:

ok single line: '973825889 987503220365627902499'

Test #42:

score: 0
Accepted
time: 13ms
memory: 4228kb

input:

996526819694097128105196470881

output:

994411349447 1002127359314908823

result:

ok single line: '994411349447 1002127359314908823'

Test #43:

score: 0
Accepted
time: 25ms
memory: 3956kb

input:

984638359916649895753226868473

output:

1913886315953 514470661976784841

result:

ok single line: '1913886315953 514470661976784841'

Test #44:

score: 0
Accepted
time: 20ms
memory: 4224kb

input:

954594052218344282851704873817

output:

3979498549097 239877974684763761

result:

ok single line: '3979498549097 239877974684763761'

Test #45:

score: 0
Accepted
time: 47ms
memory: 4004kb

input:

951130323482838313925006521277

output:

7557378146273 125854536464064349

result:

ok single line: '7557378146273 125854536464064349'

Test #46:

score: 0
Accepted
time: 45ms
memory: 4240kb

input:

962697697567853678189739826037

output:

15100422367399 63753031150060163

result:

ok single line: '15100422367399 63753031150060163'

Test #47:

score: 0
Accepted
time: 27ms
memory: 4112kb

input:

956492846963172046572961978627

output:

30582959699219 31275352561367633

result:

ok single line: '30582959699219 31275352561367633'

Test #48:

score: 0
Accepted
time: 16ms
memory: 4052kb

input:

990250331253981534128026179673

output:

61400770095961 16127653280347393

result:

ok single line: '61400770095961 16127653280347393'

Test #49:

score: 0
Accepted
time: 22ms
memory: 4084kb

input:

963782379204510691122291047909

output:

244564652505673 3940808163935933

result:

ok single line: '244564652505673 3940808163935933'

Test #50:

score: 0
Accepted
time: 41ms
memory: 4232kb

input:

955342769363561101863533963531

output:

973806882626147 981039245468473

result:

ok single line: '973806882626147 981039245468473'