欧拉函数和快速幂

欧拉函数:

定义:

互质:互质是公约数只有1的两个整数,叫做互质整数。

欧拉函数:欧拉函数,即 表示的是小于等于n并且和n互质的数的个数。

比如说 φ(1) = 1。当n是质数的时候,显然有 (n)=n-1。

如何求1~n中和n互质的数的个数?

容质原理:

1.从1~n中去掉p1,p2....pk的倍数(此时可能存在多去的情况,例如一个数既是p1的倍数又是p2的倍数)

2.加上所有pi*pj的倍数(此时如果一个数既是p1,p2的倍数又是p3的倍数,此时加三次减三次,没有变化但我们需要去除)

3.减去所有pi*pj*pk

4.加上pi*pj*pk*pd....

依次类推合并得到

,其中p1,p2.....pn是n的质因子

题目:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
/*
先试除法分解质因数,在分解过程中如果遇到质因子,那么就用公式计算欧拉函数的结果
*/
int main() {
    int n; cin >> n;
    while(n--){
        int x; cin >> x;
        int res = x;
        for(int i = 2; i < x / i; i++){
            if(x % i == 0){
                // 为了除尽,将res * (1 - 1/i) -> res * (i - 1) / i
                res = res * (i - 1) / i;
                while(x % i == 0) x /= i; 
            }
        }
        if(x > 1) res = res * (x - 1) / x;
        cout << res << '\n';
       
    }
    return 0;
}

筛法求欧拉函数:

求1~n之间所有数的欧拉函数就可以用筛选法

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6+10;
int cnt,prime[N],phi[N];
bool st[N];
ll get_eulers(int n){
    phi[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!st[i]){
            //质数
            prime[cnt++] = i;
            phi[i] = i - 1;
        }
        // 质数的倍数标记为不是质数
        for(int j = 0; prime[j] <= n / i; j++){
            st[prime[j] * i] = true;
            // Prime[j]是i其中的质因子
            if(i % prime[j] == 0){
                phi[prime[j] * i] = phi[i] * prime[j];
                break;
            }
            phi[prime[j]*i] = phi[i] * (prime[j] - 1);
        }
    }
    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) <<'\n';
    return 0;
}

快速幂:

快速幂:

快速幂算法的目标是计算。传统的做法是通过循环将 a 连续乘 k 次,时间复杂度是 O(k)。但快速幂算法利用了二进制表示的特性,将这个过程优化到了 O(log⁡k)

b个数之间我们不难发现规律:每一个数都是前一个数平方%p。

题目:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int n;
int ksm(int a,int k,int p){
    int res = 1;
    while(k){
        //如果在二进制当中该位是1的话就要累乘到res中
        if(k & 1) res = (ll) res * a % p;
        k >>= 1;// 相当处理下一位
        //每一个数都是前一个数平方%p
        a = (ll)a * a % p;
    }
    return res;
}

int main() {
    scanf("%d",&n);
    while(n--){
        int a,k,p;
        scanf("%d %d %d",&a,&k,&p);
        printf("%d\n",ksm(a,k,p));
    }
    return 0;
}

快速幂求逆元:

对于这类问题,其实就是找到一个数x,能够使得

根据费马小定理:

我们可以知道对于素数来说,,所以对于a来说

故对于质数a来说,该逆元就是****。

至于无解的情况就是a是p的倍数,此时,不可能为1。

题目:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int n;
int ksm(int a,int k,int p){
    int res = 1;
    while(k){
        //如果在二进制当中该位是1的话就要累乘到res中
        if(k & 1) res = (ll) res * a % p;
        k >>= 1;// 相当处理下一位
        //每一个数都是前一个数平方%p
        a = (ll)a * a % p;
    }
    return res;
}

int main() {
    scanf("%d",&n);
    while(n--){
        int a,p;
        //如果a是p的倍数那么一定无解
        //如果 不是,根据费马定理可以构造出解
        scanf("%d %d",&a,&p);
        int res = ksm(a,p-2,p);
        //p == 2的时候,一定返回的是1
        if(a % p) printf("%d\n",res);
        else puts("impossible");
    }
    return 0;
}
相关推荐
进击的横打10 分钟前
【车载开发系列】安全算法与安全访问
算法·安全·车载系统
努力学算法的蒟蒻11 分钟前
day59(1.18)——leetcode面试经典150
算法·leetcode·职场和发展
666HZ66613 分钟前
数据结构3.0 栈、队列和数组
开发语言·数据结构·算法
知乎的哥廷根数学学派13 分钟前
基于物理引导和不确定性量化的轻量化神经网络机械退化预测算法(Python)
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
程序员-King.15 分钟前
day146—递归—验证二叉搜索树(LeetCode-98)
算法·leetcode·二叉树·递归
永远都不秃头的程序员(互关)16 分钟前
【K-Means深度探索(五)】不止欧氏距离:K-Means中距离度量那些事儿
算法·机器学习·kmeans
tobias.b19 分钟前
408真题解析-2009-41-数据结构-最短路径
数据结构·算法·计算机考研·408考研·408真题解析
王老师青少年编程20 分钟前
2024年9月GESP真题及题解(C++七级): 矩阵移动
c++·算法·题解·真题·gesp·七级·矩阵移动
棒棒的皮皮27 分钟前
【深度学习】YOLO 进阶提升之算法改进(新型骨干网络 / 特征融合方法 / 损失函数设计)
深度学习·算法·yolo·计算机视觉
pas13632 分钟前
33-mini-vue 更新element的children-双端对比diff算法
javascript·vue.js·算法