POJ:1808
链接:http://poj.org/problem?id=1808
题意:给定a,n(n为质数) 问 x^2 ≡ a (mod n) 是否有解
可以用a^((n - 1)/2) ≡ ±1(mod n) 当为1是二次剩余,为-1是非二次剩余
但上述方法仅仅是判断是否有解,下面的方法能够求最小整数解
Ural(Timus) 1132
链接: http://acm.timus.ru/problem.aspx?space=1&num=1132
题意:给定a,n(n为质数) 问 x^2 ≡ a (mod n) 是否有解,如果有解按照从小到大输出解
代码:
typedef long long ll; using namespace std; ll pow_mod(ll a, ll n, ll p) { ll res = 1; while (n) { if (n & 1) res = res * a % p; n >>= 1; a = a * a % p; } return res; } ll legendre(ll a, ll p) { return pow_mod(a, (p - 1) >> 1, p); } ll mod(ll a, ll p) { a %= p; if (a < 0) a += p; return a; } struct node { static ll p, omega; ll a, b; node(ll a, ll b): a(a % p), b(b % p) {} }; node operator *(const node &p, const node &q) { int m = node::p; return node(p.a * q.a + p.b * q.b % m * node::omega, p.a * q.b + q.a * p.b); } node pow_mod(node a, ll n) { node result(1, 0); while (n > 0) { if ((n & 1) == 1) { result = result * a; } a = a * a; n >>= 1; } return result; } ll node::p, node::omega; ll modsqr(ll a, ll p) { if (p == 2) return 1; if (legendre(a, p) + 1 == p) return -1; if ((((p + 1) >> 1) & 1) == 0) return pow_mod(a, (p + 1) >> 2, p); ll a_0 = -1; while (true) { a_0 = rand() % p; if (legendre(mod(a_0 * a_0 - a, p), p) + 1 == p) break; } node::p = p; node::omega = mod(a_0 * a_0 - a, p); node ret = pow_mod(node(a_0, 1), (p + 1) >> 1); //assert(ret.b == 0); return ret.a; } int main () { int t; int a, n; scanf("%d", &t); while(t--) { scanf("%d%d", &a, &n); a %= n; int x = modsqr(a, n); if (x == -1) puts("No root"); else { if (x * 2 > n) x = n - x; if (x != n - x) printf("%d %d\n", x, n - x); else printf("%d\n", x); } } return 0; }