【URAL - 1132】 Square Root

在这里插入图片描述
在这里插入图片描述

ThoneLLi_Shanks算法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll pow_mod(ll a,ll b,ll c) {
	ll ans = 1; a = a % c;
	while (b) {
		if (b & 1) ans = ans * a % c;
		b >>= 1; a = a * a % c;
	}
	return ans;
}

ll ToneLLi_Shanks(ll n,ll p) {
	if (p == 2) return (n & 1) ? 1 : -1;
	if (pow_mod(n, p>>1, p) != 1) return -1;
	if (p & 2) return pow_mod(n, p + 1 >> 2, p);
	int s = __builtin_ctzll(p ^ 1);
	ll q = p >> s,z = 2;
	for (; pow_mod(z, p >> 1, p) == 1; ++z);
	ll c = pow_mod(z, q, p);
	ll r = pow_mod(n, q + 1 >> 1, p);
	ll t = pow_mod(n, q, p), tmp;
	for (int m = s, i; t != 1; ++i) {
		for (i = 0, tmp = t; tmp != 1; ++i) tmp = tmp * tmp % p;
		for(; i < --m;) c = c * c % p;
		r = r * c % p;
		c = c * c % p;
		t = t * c % p;
	}
	return r;
}

int main() {
	int T; cin >> T;
	while (T--) {
		int n, p; cin >> n >> p;
		int ans = ToneLLi_Shanks(n, p);
		if (ans == -1) {
			puts("No root");
		} else if (ans * 2 == p) {
			cout << ans << endl;
		} else {
			cout << min(ans, p - ans) << " " << max(ans, p - ans) << endl;
		}
	}
	return 0;
}


Cipolla 算法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll p, w, n;
struct Quadratic{
	ll x, y;
	Quadratic () {};
	Quadratic(ll x,ll y) {
		this->x = x;
		this->y = y;
	}
};

Quadratic multi(Quadratic a,Quadratic b,ll c) {
	Quadratic ans;
	ans.x = (a.x * b.x % c + a.y * b.y % c * w % c) % c;
	ans.y = (a.x * b.y % c + a.y * b.x % c) % c;
	return ans;
}

Quadratic quick_pow(Quadratic a,ll b,ll c) {
	Quadratic ans = Quadratic(1, 0);
	while (b) {
		if (b & 1) ans = multi(ans, a, c);
		a = multi(a, a, c); b >>= 1;
	}
	return ans;
}

ll pow_mod(ll a,ll b,ll c) {
	ll ans = 1; a = a % c;
	while (b) {
		if (b & 1) ans = ans * a % c;
		b >>= 1; a = a * a % c;
	}
	return ans;
}

ll Cipolla(ll n,ll p) {
	n %= p; ll b, t;
	if (n == 0) return 0;
	if (p == 2) return n;
	if (pow_mod(n, p - 1 >> 1, p) == p - 1) return -1;
	while (true) {
		b = rand() % p;
		t = b * b - n;
		w = (t % p + p) % p;
		if (pow_mod(w, p - 1 >> 1, p) == p - 1) break;
	}
	Quadratic ans = Quadratic(b, 1);
	ans = quick_pow(ans, p + 1 >> 1, p);
	return ans.x;
}

int main() {
	int T; cin >> T;
	while (T--) {
		cin >> n >> p;
		ll ans = Cipolla(n, p);
		if (ans == -1) puts("No root");
		else if (ans * 2 == p) cout << ans << endl;
		else cout << min(ans, p-ans) << " " << max(ans, p-ans) << endl;
	}
	return 0;
}





发布了26 篇原创文章 · 获赞 3 · 访问量 2410

猜你喜欢

转载自blog.csdn.net/BX2359575459/article/details/103420595