欧拉函数
公式法:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
while (n -- )
{
int a;
cin >> a;
int res = a;
for (int i = 2; i <= a / i; i ++ )
{
if (a % i == 0)
{
res = res / i * (i - 1);// 先处理res/i 防止除法向下取整导致最后结果不准确
while (a % i == 0) a /= i;// 欧拉函数与约数的指数无关
}
}
if (a > 1) res = res / a * (a - 1);
cout << res << endl;
}
return 0;
}
筛法:
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1000010;
int primes[N], cnt;
int phi[N];
bool st[N];
LL get_eulers(int n)
{
phi[1] = 1;//
for (int i = 2; i <= n ; i ++ )
{
if(!st[i])
{
primes[cnt ++ ] = i;
phi[i] = i - 1;//
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) // primes[j]为i的一个质因子, 但不是primes[j] * i的最小质因子,之前在phi[i]中已经计算过primes[j]出现的情况
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);// primes[j]为 primes[j] * i的一个最小质因子
}
}
LL res = 0;
for (int i = 1; i <= n; i ++ ) res += phi[i];
return res;
}
int main()
{
int n;
cin >> n;
cout << get_eulers(n) << endl;
return 0;
}
快速幂
#include <iostream>
using namespace std;
typedef long long LL;
int qmi(int a, int k, int p)
{
int res = 1;
while (k)// k内存中是二进制
{
if (k & 1) res = (LL)res * a % p;
k >>= 1;
a = (LL)a * a % p;
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, k, p;
scanf("%d%d%d", &a, &k, &p);
printf("%d\n", qmi(a, k, p));
}
return 0;
}
快速幂求逆元
#include <iostream>
using namespace std;
typedef long long LL;
int qmi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1) res = (LL)res * a % p;
k >>= 1;
a = (LL)a * a % p;
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, p;
scanf("%d%d", &a, &p);
int res = qmi(a, p - 2, p);
if (a % p) printf("%d\n", res);
else puts("impossible");
}
return 0;
}
扩展欧几里得算法
#include<iostream>
using namespace std;
int exgcd(int a, int b, int &x, int &y) // 引用带回解x, y
{
if (!b)// b为0时
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
int n;
cin >> n;
while (n -- )
{
int a, b, x, y;
cin >> a >> b;
exgcd(a, b, x, y);
cout << x << " " << y << endl;
}
return 0;
}
线性同余方程
#include<iostream>
using namespace std;
typedef long long LL;
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;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, b, m;
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y);
if (b % d) puts("impossible");
else printf("%d\n", (LL)x * (b / d) % m);
}
return 0;
}
中国剩余定理
表达整数的奇怪方式