原理
求解方法
实现
LL modSqrt(LL a, LL p) {
if(p == 2) return a%p;
if(powMod(a, (p-1)>>1, p) != 1) return -1;
if(p%4 == 3) return powMod(a, (p+1)>>2, p);
LL b, x;
for(b = 1; powMod(b, (p-1)>>1, p) == 1; ++b);
LL i = (p-1)>>1, k = 0;
do {
i >>= 1, k >>= 1;
if((powMod(a, i, p)*powMod(b, k, p)+1)%p == 0) k += ((p-1)>>1);
} while(i%2 == 0);
x = (powMod(a, (i+1)>>1, p)*powMod(b, k>>1, p)) % p;
return x;
}
struct node {
LL p, d;
};
node mulMod(node a, node b, LL w, LL p) {
node c;
c.p = (a.p*b.p%p + a.d*b.d%p*w%p)%p;
c.d = (a.p*b.d%p + a.d*b.p%p)%p;
return c;
}
node powMod(node a, LL b, LL w, LL p) {
node r; r.p = 1, r.d = 0;
while(b) {
if(b&1) r = mulMod(r, a, w, p);
a = mulMod(a, a, w, p);
b >>= 1;
}
return r;
}
LL modSqrt(LL a, LL p) {
a %= p;
if(p == 2) return a%p;
if(powMod(a, (p-1)>>1, p)== p-1) return -1;
LL b = -1, w;
while(1) {
b = rand() % p;
w = b*b - a; w = (w+p)%p;
if(powMod(w, (p-1)>>1, p) == p-1) break;
}
node r, ans; r.p = b, r.d = 1;
ans = powMod(r, (p+1)>>1, w, p);
return ans.p;
}
模为合数的解法
应用
Square Root URAL - 1132