对于每一个数字,分别从定义出发求其欧拉函数:
#include
using namespace std;
int main() {
int m; cin >> m;
while (m--) {
int num; cin >> num;
int res = num;//最后结果
//1.分解质因数
for (int i = 2; i <= num / i; ++i) {
if (num % i == 0) {
/* i为num的一个因子 */
res = res / i * (i - 1);//res = res * (1 - 1/i);公式内容
while (num % i == 0) num /= i;
}
}
//2.说明num有一个大于1的质因数
if (num > 1) res = res / num * (num - 1);
cout << res << endl;
}
return 0;
}
res = res / num * (num - 1)
中, 不能写成 res = res * (num - 1) / num;
顺序不可颠倒如果需要求出1~N中,每一个数字的欧拉函数,这时再使用公式法(将每个数都分解质因数)将导致时间复杂度为 O ( n ) = n n O(n) = n\sqrt{n} O(n)=nn
在筛法求素数的过程中,计算出每一个数的欧拉函数:
#include
#include
using namespace std;
const int MAX = 1000010;
int primes[MAX], cnt;//质数数组、质数下标
bool st[MAX];//每个数字是否已经被筛选掉
int phi[MAX];
long long 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) {//优化为线性的
phi[primes[j] * i] = phi[i] * primes[j];//数学推导
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);//数学推导
}
}
//计算总和
long long 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;
}
快速幂的核心:反复平方法
快速幂即快速的求出 a k m o d p a^k~mod~p ak mod p 的结果,可以在 O ( l o g k ) O(logk) O(logk) 的时间复杂度内求出结果,其中满足 1 ≤ a , p , k ≤ 1 0 9 1~≤~a~,~p~,~k~≤~10^9 1 ≤ a , p , k ≤ 109,
//暴力法O(k)
res = 1;
for (int i = 1; i <= k; ++i) {
res = res * a % p;
}
//快速幂O(logk)
int res = 1;
while (k) {
if (k & 1) res = (long long)res * a % p;
k >>= 1;//最后一位抹去
a = (long long)a * a % p;
}
return res;
#include
using namespace std;
//a^k % p
int qmi(int a, int k, int p) {
int res = 1;
while (k) {
if (k & 1) res = (long long)res * a % p;
k >>= 1;//最后一位抹去
a = (long long)a * a % p;
}
return res;
}
int main() {
int m;
scanf("%d", &m);
while (m--) {
int a, k, p;
scanf("%d%d%d", &a, &k, &p);
printf("%d\n", qmi(a, k, p));
}
return 0;
}
#include
using namespace std;
//a^k % p
int qmi(int a, int k, int p) {
int res = 1;
while (k) {
if (k & 1) res = (long long)res * a % p;
k >>= 1;//最后一位抹去
a = (long long)a * a % p;
}
return res;
}
int main() {
int m;
scanf("%d", &m);
while (m--) {
int a, p;
scanf("%d%d", &a, &p);
int res = qmi(a, p - 2, p);
if (a % p) printf("%d\n", res);//res != 0 表示a不是p的倍数
else puts("impossible");//a是p的倍数
}
return 0;
}
#include
using namespace std;
// (a, b) = (b, a mod b)
// return b ? gcd(b, a % b) : a;
int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a % b);
}
// ax + by = (a, b)
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 m;
scanf("%d", &m);
while (m--) {
int a, b, x, y;
scanf("%d%d", &a, &b);
exgcd(a, b, x, y);
printf("%d %d\n", x, y);
}
return 0;
}
#include
using namespace std;
// (a, b) = (b, a mod b)
// return b ? gcd(b, a % b) : a;
int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a % b);
}
// ax + by = (a, b)
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 m;
scanf("%d", &m);
while (m--) {
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", (long long)x * (b / d) % m);
}
return 0;
}