数论基础学习笔记
stripe_python · · 算法·理论
素数
简单知识
定义
素数有简单的
inline bool isprime(int x) {
if (x <= 1) return false;
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
for (int i = 5; i * i <= x; i += 6) {
if (x % i == 0 || x % (i + 2) == 0) return false;
}
return true;
}
原理的话,对于正整数
算术基本定理
任何一个合数
存在性:用反证法,假设
唯一性:用反证法,假设
Exgcd
裴蜀定理
对于任意非零整数
不定方程
由
递归式:
void exgcd(int a, int b, int& x, int& y) {
if (b == 0) return x = 1, y = 0, void();
exgcd(b, a % b, x, y);
int t = x;
x = y, y = t - a / b * y;
}
乘法逆元
求
移项得:
欧拉函数
定义
设
这样通过分解质因数,可以
inline int phi(int n) {
if (n == 1) return 1;
int res = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
res = res / i * (i - 1);
while (n % i == 0) n /= i;
}
}
if (n > 1) res = res / n * (n - 1);
return res;
}
由于欧拉函数是积性函数,可以用线性筛计算。
int n, len, phi[N], prime[N];
bool isprime[N];
inline void eular(int n) {
phi[1] = 1;
for (int i = 2; i <= n; i++) isprime[i] = true;
for (int i = 2; i <= n; i++) {
if (isprime[i]) prime[++len] = i, phi[i] = i - 1;
for (int j = 1; j <= len && i * prime[j] <= n; j++) {
isprime[i * prime[j]] = false;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
经典定理
费马小定理
当
证明:找到
同乘
也即
应用:当
欧拉定理
若
证明:找到
同乘
Lucas 定理
若
这样就可以
namespace Lucas {
long long a[N];
long long power(long long x, int y, int p) {
long long res = 1; x %= p;
for (; y; y >>= 1) {
if (y & 1) res = (res * x) % p;
x = (x * x) % p;
}
return res;
}
inline long long cm(long long n, long long m, int p) {
if (m > n) return 0;
return (a[n] * power(a[m], p - 2, p)) % p
* power(a[n - m], p - 2, p) % p;
}
inline long long lucas(long long n, long long m, int p) {
if (m == 0) return 1;
return cm(n % p, m % p, p) * lucas(n / p, m / p, p) % p;
}
inline long long C(int n, int m, int p) {
a[0] = 1;
for (int i = 1; i <= p; i++) a[i] = (a[i - 1] * i) % p;
return lucas(m, n, p);
}
}