【笔记】数论基础

  • 乘法逆元

\(a\times b \equiv 1 (\bmod \ c)\),且 \(\gcd(a,b) = 1\),那么我们定义 \(a\)\(b\) 的逆元,也可以称 \(a\)\(b\)\(\bmod \ c\) 意义下的倒数。

  • 费马小定理

对于质数 \(p\) 和任意整数 \(a\),有 \(a^p \equiv a (\bmod \ p)\)。反之,若 \(a^p \equiv a (\bmod \ p)\),则 \(p\) 很有可能是质数。

对于上面的式子 \(a^p \equiv a (\bmod \ p)\),可以两边同时约去一个 \(a\),则有 \(a^{p-1} \equiv 1 (\bmod \ p)\)

也就是说,如果我们要判断 \(p\) 是否为质数,我们可以随机选取一个整数 \(a\),然后计算 \(a^{p-1} (\bmod \ p)\),如果结果不为 \(1\),那么 \(p\) 一定不是质数。

  • 二次探测定理 / \(\mathcal{Fermat}\) 测试

如果 \(p\) 是奇质数,则有 \(a^2 \equiv 1 (\bmod \ p)\) 的解为 \(a \equiv 1\)\(a \equiv p - 1 (\bmod \ p)\)

证明如下:

\[a^2 \equiv 1 (\bmod \ p) \]

\[a^2 - 1 \equiv 0 (\bmod \ p) \]

\[(a - 1)\times(a + 1) \equiv 0 (\bmod \ p) \]

\[a \equiv 1 \ or\ a \equiv p - 1 (\bmod \ p) \]

  • \(\mathcal{Miller-Rabin}\) 质数测试

判断一个正整数 \(p\) 是否为质数 \((p \le10^{18})\)

对于暴力做法:

bool isPrime(int a) {
  if (a < 2) return 0;
  for (int i = 2; i < a; ++i)
    if (a % i == 0) return 0;
  return 1;
}

显然超时。

需要用到 \(\mathcal{Miller-Rabin}\) 质数测试。

将费马小定理与二次探测定理结合,即为 \(\mathcal{Miller-Rabin}\) 质数测试。

单次测试失败概率为 \(\frac{1}{4}\),若进行了 \(k\) 轮测试,那么失败的概率为 \((\frac{1}{4})^k\)

在进行 \(5\) 轮测试的情况下,失败的概率为 \(\frac{1}{0.0009765625}\),这几乎不可能发生。

当然这里的 \(k\) 最好在 \([8,20]\) 之间。

关于单轮的时间复杂度为 \(\mathcal{O(\log n)}\),总时间复杂度为 \(\mathcal{O(k\log n)}\)

注意:需要使用 __int128,用 long long 会爆掉。

#include <iostream>
#define int long long
using namespace std;
int p, k;
int qmul(int a, int b, int mod) {
	int c = (long double)a / mod * b;
	int res = (unsigned int)a * b - (unsigned int)c * mod;
	return (res + mod) % mod;
}
int quickpow(int a, int n, int mod) {
	int res = 1;
	while (n) {
		if (n & 1) res = qmul(res, a, mod);
		a = qmul(a, a, mod);
		n >>= 1;
	}
	return res;
}
bool MR(int n) {
	if (n < 3) {
		return n == 2;
	}
	for (int i = 1; i <= k; i ++) {
		int a = rand() % (n - 2) + 2;
		if (quickpow(a, n - 1, n) != 1) {
			return 0;
		}
	}
	return 1;
}
signed main() {
	cin >> p >> k;
	cout << MR(p);
	return 0;
}
posted @ 2024-06-01 21:40  Xssion37_XY  阅读(33)  评论(0)    收藏  举报