QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#811254 | #998. 素数分解 | kzoacn | AC ✓ | 47ms | 4256kb | C++14 | 8.6kb | 2024-12-12 17:01:37 | 2024-12-12 17:01:37 |
Judging History
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'