数论学习笔记
概念不说了。
同余方程
同余方程基本形式:
代码:
int exgcd (int a, int b, int& x, int& y) { if (!b) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
乘法逆元
若
求解乘法逆元的方法:
- 扩欧,相当于 解
。适合求某一个数的逆元。 - 费马小定理,若
是质数,且 ,则 ,那么 。适用于 为质数的情况。 - 线性递推求逆元,适合求
的逆元。
总之,我觉得要求单个的逆元就用扩欧,多个的逆元就用线性递推,费马小定理随便。
中国剩余定理
这里直接讲扩展中国剩余定理。
定义:线性同余方程组,不要求模数两两互质。
就是求这个方程的一个解。
解法
采用数学归纳法。
- 假设前
个方程的特解为 ,那么通解为 ,其中 。 - 求解
,使得 。 - exgcd 判断是否有解,若有解,则
。
代码:
#include <bits/stdc++.h> #define int long long using namespace std; const int kMaxN = 1e5 + 5; int n, a[kMaxN], b[kMaxN]; int M = 1; __int128 res, x, y; __int128 mod (__int128 x, __int128 m) { return (x % m + m) % m; } __int128 add (__int128 x, __int128 y, __int128 m) { return (x + y >= m) ? (x + y - m) : (x + y); } __int128 times (__int128 x, __int128 y, __int128 m) { return 1ll * x * y % m; } __int128 gcd (__int128 m, __int128 n) { return (!n) ? m : gcd(n, m % n); } __int128 lcm (__int128 m, __int128 n) { return m / gcd(m, n) * n; } __int128 exgcd (__int128 a, __int128 b, __int128& x, __int128& y) { if (!b) { x = 1, y = 0; return a; } __int128 d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } __int128 inv (__int128 a, __int128 m) { __int128 x, y; exgcd(a, m, x, y); return mod(x, m); } signed main() { cin >> n; for (int i = 1; i <= n; ++i) { cin >> a[i] >> b[i]; } res = b[1], M = a[1]; for (int i = 2; i <= n; ++i) { __int128 s = mod(b[i] - mod(res, a[i]), a[i]); __int128 d = exgcd(M, a[i], x, y); __int128 m = M; M = lcm(M, a[i]); x = mod(times(x, s / d, a[i]), a[i]); // cout << "***" << i << ' ' << res << endl; res += times(x, m, M); res = mod(res, M); } // cout << exgcd(4, 48, x, y) << endl; cout << (long long)res << endl; return 0; }
欧拉函数
对于
- 性质一:若
是质数, 。 - 性质二:若
, 。 - 性质三:若
, 。
公式:
欧拉定理
若
推论:
若
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步