xgzc— math 专题训练(二)

费马小定理&欧拉定理

费马小定理:
如果\(p\)是一个质数,而整数\(a\)不是\(p\)的倍数,\(a^{p-1}\equiv1\pmod p\)
欧拉定理:
\(a\)\(n\)互质时,\(a^b \equiv a^{b\%\phi(n)} \pmod n\)
扩展欧拉定理:

\[a^b \equiv \begin{cases} a^b\pmod n (b<\phi(n))\\ a^{b\%\phi(n)+\phi(n)\pmod n (b\ge\phi(n))}\\ \end{cases} \]

BSGS

求方程\(a^x\equiv b\pmod p\)(\(a\)\(p\)互质)的解
\(m=\lceil \sqrt p\rceil\),设\(x = m*i-j\)
那么易知,\((a^m)^i\equiv b*a^j\pmod p\)
我们可以把右边的全部丢到\(map\)里,然后枚举左边的,看看\(map\)中有没有


map<int, int> M;
int BSGS(int a, int b, int p) {
	if (b == 1 && a) return 0;
	M.clear(); int m = ceil(sqrt(p));
	LL t = 1;
	for (int i = 0; i < m; i++, t = t * a % p) M[t * b % p] = i;
	for (int i = 1, s = t; i <= m + 1; i++, s = t * s % p) {
		map<int, int> :: iterator it = M.find(s);
		if (it == M.end()) continue;
		return m * i - (it->second);
	}
	return -1;
}
int main() {
	int a, b, p;
	while (scanf("%d%d%d", &p, &a, &b) != EOF) {
		int ans = BSGS(a, b, p);
		if (ans == -1) puts("no solution");
		else printf("%d\n", ans);	
	}
	return 0;
}

EXBSGS

\(a\)\(p\)不互质时,就不能除过去。
考虑,\(a^x=p*z+b\)
我们取\(d = gcd(a,p)\)
如果\(b\)不是\(d\)的倍数显然无解
然后整体除\(d\)得到\(\frac{a}{d}a^{x-1}=\frac{p}{d}*z+\frac{b}{d}\)
显然可以递归处理。。
记录一下系数
然后最后回带一下即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Mod = 1e5 + 7;
int gcd(int x, int y) {
	return !y ? x : gcd(y, x % y);
}
struct Hash {
	struct node {
		int a, b, nxt;
	} A[1000010];
	int lst[Mod], tot;
	void clear() { memset(lst, 0, sizeof(lst)); tot = 0; }
	void add(int a, int b, int S) {
		A[++tot] = (node) {a, b, lst[S]};
		lst[S] = tot;
	}
	void insert(int a, int b) { add(a, b, a % Mod); }
	int find(int x) {
		for (int i = lst[x % Mod]; i; i = A[i].nxt)
			if (A[i].a == x) return A[i].b;
		return -1;
	}
} M;
int exBSGS(int a, int b, int p) {
	if (b == 1 && a) return 0;
	int d, k = 0, s = 1;
	while ((d = gcd(a, p)) > 1) {
		if (b % d) { return -1; }
		b /= d; p /= d; k++; s = 1ll * s * a / d % p;
		if (s == b) { return k; }
	}
	M.clear(); int m = ceil(sqrt(p));
	LL t = 1;
	for (int i = 0; i < m; i++, t = t * a % p) M.insert(t * b % p, i);
	s = t * s % p;
	for (int i = 1; i <= m + 1; i++, s = t * s % p) {
		int it = M.find(s); if (it == -1) continue;
        return m * i - it + k;
	}
	return -1;
}
int main() {
	int a, b, p;
	while (scanf("%d%d%d", &a, &p, &b) != EOF) {
		if (!a && !b && !p) return 0;
		int ans = exBSGS(a, b, p);
		if (ans == -1) puts("No Solution");
		else printf("%d\n", ans);
	}
	return 0;	
}

exLucas

二次剩余(Cipolla)

posted @ 2019-09-15 18:24  zzy2005  阅读(246)  评论(0编辑  收藏  举报