1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| namespace Math { int n, p, w; struct P { int x, y; }; inline P mul(const P &x, const P &y, int p) { P res; res.x = (1ll * x.x * y.x + 1ll * x.y * y.y % p * w % p) % p; res.y = (1ll * x.y * y.x + 1ll * x.x * y.y) % p; return res; } int ksm(int x, int y, int p) { int w = 1; for(; y; y >>= 1, x = 1ll * x * x % p) if(y & 1) w = 1ll * w * x % p; return w; } int Pow(P x, int y, int p) { P w = (P){1, 0}; for(; y; y >>= 1, x = mul(x, x, p)) if(y & 1) w = mul(w, x, p); return w.x; } int calc(int x, int p) { x %= p; if(p == 2) return x; if(ksm(n, (p - 1) / 2, p) == p - 1) return -1; int ans; for(;;) { ans = rand() % p, w = (1ll * ans * ans % p - x + p) % p; if(ksm(w, (p - 1) / 2, p) == p - 1) break; } P t = (P){ans, 1}; return Pow(t, (p + 1) / 2, p); } int Sqrt(int x, int pr) { n = x, p = pr; if(!x) return 0; return calc(x, p); } } using Math::Sqrt;
|