| 4 | if (p == 2) return 1; |
| 5 | return mod_pow(a, (p-1)/2, p) == 1 ? 1 : -1; } |
| 6 | ll tonelli_shanks(ll n, ll p) { |
| 7 | assert(leg(n,p) == 1); |
| 8 | if (p == 2) return 1; |
| 9 | ll s = 0, q = p-1, z = 2; |
| 10 | while (~q & 1) s++, q >>= 1; |
| 11 | if (s == 1) return mod_pow(n, (p+1)/4, p); |
| 12 | while (leg(z,p) != -1) z++; |
| 13 | ll c = mod_pow(z, q, p), |
| 14 | r = mod_pow(n, (q+1)/2, p), |
| 15 | t = mod_pow(n, q, p), |
| 16 | m = s; |
| 17 | while (t != 1) { |
| 18 | ll i = 1, ts = (ll)t*t % p; |
| 19 | while (ts != 1) i++, ts = ((ll)ts * ts) % p; |
| 20 | ll b = mod_pow(c, 1LL<<(m-i-1), p); |
| 21 | r = (ll)r * b % p; |
| 22 | t = (ll)t * b % p * b % p; |
| 23 | c = (ll)b * b % p; |
| 24 | m = i; } |
| 25 | return r; } |
| 26 | // vim: cc=60 ts=2 sts=2 sw=2: |