欧拉函数、欧拉、费马小定理、逆元、孙子定理
欧拉函数
表示小于等于n的数中与n互质的个数
// C++ Version
int euler_phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}欧拉函数是积性函数
当n为奇数,
if ,then
当n>2时,n是偶数
n的因数的欧拉函数之和等于n
小于n的数中,与n互质的数的总和为:*n/2 (n>1)
筛法求欧拉函数
求
设是n的最小质因子,
如果,=*
如果,=*
void getPhi() {
phi[1] = 1;
for (int i = 2; i <= 5000000; i++) {
if (!phi[i]) {
for (int j = i; j <= 5000000; j += i) {
if (!phi[j])
phi[j] = j;
phi[j] = phi[j] / i * (i - 1);
}
}
}
}// C++ Version
void pre() {
memset(is_prime, 1, sizeof(is_prime));
int cnt = 0;
is_prime[1] = 0;
phi[1] = 1;
for (int i = 2; i <= 5000000; i++) {
if (is_prime[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= cnt && i * prime[j] <= 5000000; j++) {
is_prime[i * prime[j]] = 0;
if (i % prime[j])
phi[i * prime[j]] = phi[i] * phi[prime[j]];
else {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
}欧拉定理
如果,那么
即对于, a有逆元
那么
费马小定理
设p为质数,且
逆元
求逆元的两种方法:
设m为正整数,,逆元
设p为质数,逆元
线性同余方程
求同余方程的解
方程与方程是等价的,有整数解的充要条件为。
根据扩展欧几里得求解
最后通解为
若要求x的最小非负整数解
// C++ Version
int ex_gcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = ex_gcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return d;
}
bool liEu(int a, int b, int c, int& x, int& y) {
int d = ex_gcd(a, b, x, y);
if (c % d != 0) return 0;
int k = c / d;
x *= k;
y *= k;
return 1;
}同余方程组
当k=2时,,即,由扩展欧几里得,,故
当且仅当时有解,解的形式为
当k不等于2时,每次对两个同余方程进行操作,操作k次,可得解的形式为
解一元线性同余方程组
可转化为
同余方程组的构造解
中国剩余定理
设是两两互质的k个正整数
则方程组
其中
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
//注意在实际调用时,*a是模数(相当于同余式中的m),*r是余数(相当于同余式中的a)
ll CRT(ll k, ll* a, ll* r) {
ll n = 1, ans = 0;
for (int i = 1; i <= k; i++) n = n * r[i];
for (int i = 1; i <= k; i++) {
ll m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}扩展中国剩余定理
在中国剩余定理的基础上
若 不一定两两互质,那么此时可能会存在无解的情况,
//偷绒绒的板子
ll A[N], M[N];
ll exGCD(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1, y = 0;
return a;
}
ll gcd = exGCD(b, a % b, x, y), tmpx = x;
x = y;
y = tmpx - a / b * y;
return gcd;
}
ll mul(ll a, ll b, ll p) {
ll ans = 0;
for (; b; b >>= 1, (a <<= 1) %= p)
if (b & 1)(ans += a) %= p;
return ans;
}
ll exCRT(int n) {
ll a1 = A[1], m1 = M[1];
for (int i = 2; i <= n; ++i) {
ll a2 = (A[i] % M[i] + M[i]) % M[i], m2 = M[i], x, y;
ll gcd = exGCD(m1, m2, x, y);
ll del = ((a1 - a2) % m2 + m2) % m2;
if (del % gcd)return -1ll;
ll k1 = -mul(x, del / gcd, m2 / gcd);
a1 += m1 * k1;
m1 = m1 / gcd * m2;
a1 = (a1 % m1 + m1) % m1;
}
return a1;
}扩展欧拉定理
Last updated