本文用于记录个人算法竞赛学习,仅供参考
目录
一.欧拉函数
二.欧拉函数模板
三.用筛法求每个数的欧拉函数
四.快速幂
五.扩展欧几里得算法
六.用扩展欧几里得算法求线性同余方程
一.欧拉函数
即有一个数n, n通过质因数分解得到
通过欧拉函数有
证明:容斥原理
二.欧拉函数模板
实际上就是分解质因数
时间复杂度:O()
//计算一个数的欧拉函数的值
int phi(int x)
{
int result = x;
//分解质因数
for (int i = 2; i <= x / i; i++)
{
if (x % i == 0)
{
//注意变形
result = result / i * (i - 1);
//将质数i除干净
while (x % i == 0)
x /= i;
}
}
if (x > 1)
result = result / x * (x - 1);
return result;
}
三.用筛法求每个数的欧拉函数
求一个数的欧拉函数是O(), 用遍历每个数的方法来求每个数欧拉函数时间复杂度是O(),用筛法求每个数的欧拉函数只需要O(n)
//筛法求欧拉函数
const int N = 100;
int primes[N], cnt; //primes存储素数,cnt用于计数
int eulers[N]; //存储每个数的欧拉函数
bool st[N]; //st判断该数是否被筛掉
void get_eulers(int n)
{
eulers[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[cnt++] = i;
eulers[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j++)
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)
{
eulers[t] = eulers[i] * primes[j];
break;
}
eulers[t] = eulers[i] * (primes[j] - 1);
}
}
}
四.快速幂
//求 m^ k mod p,时间复杂度 O(logk)。
int qmi(int m, int k, int p)
{
int result = 1;
int t = m;
while (k)
{
if (k & 1)
result = result * t % p;
t = t * t % p;
k >>= 1;
}
return result;
}
五.扩展欧几里得算法
//扩展欧几里得算法
//ax + by = gcd(a,b),求x,y
//注意xy是&
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;
}
六.用扩展欧几里得算法求线性同余方程
//扩展欧几里得算法
//ax + by = gcd(a,b),求x,y
//注意xy是&
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 = 0, y = 0;
int d = exgcd(a, m, x, y);
if (b % d != 0)
printf("impossible\n");
else
printf("%d\n", (b / d) * x % m);
}
return 0;
}