【AcWing算法基础课】第四章 数学知识(未完待续)(2)

简介: 从2到n枚举每个数,删掉其所有的倍数,枚举完之后,没有被删掉的数为质数。

二、筛素数

1.朴素筛法求素数

从2到n枚举每个数,删掉其所有的倍数,枚举完之后,没有被删掉的数为质数。


核心模板

int primes[N],cnt;   //primes[]存储所有素数
bool st[N];    //st[x]存储x是否被筛掉
void get_primes(int n){
    st[0]=st[1]=true;           //0和1均不是质数
    for(int i=2;i<=n;i++){
        if(st[i]) continue;
        primes[cnt++]=i;
        for(int j=i+i;j<=n;j+=i){
            st[j]=true;
        }
    }
}


埃氏筛法


int primes[N],cnt;   //primes[]存储所有素数
bool st[N];    //st[x]存储x是否被筛掉
void get_primes(int n){
    st[0]=st[1]=true;           //0和1均不是质数
    for(int i=2;i<=n;i++){
        if(!st[i]){
        primes[cnt++]=i;
        for(int j=i+i;j<=n;j+=i){
            st[j]=true;
        }
        }
    }
}


2.线性筛法求素数(O(n))

5962b3594ee7ebc047e90dee152d0fc5_6b52c47597a644bbb56f4c58901f5245.png


核心模板

int primes[N],cnt;   //primes[]存储所有素数
bool st[N];   //st[x]存储x是否被筛掉
void get_primes(int n){
    st[0]=st[1]=true;           //0和1均不是质数
    for(int i=2;i<=n;i++){
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=n/i;j++){
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }
    }
}


题目链接:868. 筛质数


2.1题目描述

给定一个正整数 n,请你求出 1∼n 中质数的个数。


输入格式


共一行,包含整数 n。


输出格式


共一行,包含一个整数,表示 1∼n 中质数的个数。


数据范围


1≤n≤106


输入样例:


8


输出样例:


2.2思路分析

利用上述模板即可。


2.3代码实现

埃氏筛法


#include <iostream>
using namespace std;
const int N=1000010;
int n,cnt;
int primes[N];
bool st[N];
void getPrimes(int n){
     for(int i=2;i<=n;i++){
         if(!st[i]){
            primes[cnt++]=i;
            for(int j=i+i;j<=n;j+=i){
                st[j]=true;
            }
         }
     }
}
int main(){
    cin>>n;
    getPrimes(n);
    cout<<cnt;
    return 0;
}


线性筛法


#include <iostream>
using namespace std;
const int N=1000010;
int n,cnt;
int primes[N];
bool st[N];
void getPrimes(int n){
     for(int i=2;i<=n;i++){
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=n/i;j++){
            st[i*primes[j]]=true;
            if(i%primes[j]==0) break;    //此时primes[j]一定是i的最小质因子
        }
    }     
}
int main(){
    cin>>n;
    getPrimes(n);
    cout<<cnt;
    return 0;
}


三、欧几里得算法

核心思路:a与b的最大公约数等于b与a mod b的最大公约数。

最大公约数和最小公倍数的关系:


下图内容来源:百度百科,侵删。

12d8c0528f2981272ada2e9f8e2c0c97_49957f3d531f4be3b9b71570c466f748.png

核心模板

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}


题目链接:872. 最大公约数


3.1题目描述

给定 n 对正整数 ai,bi,请你求出每对数的最大公约数。


输入格式


第一行包含整数 n。


接下来 n 行,每行包含一个整数对 ai,bi。


输出格式


输出共 n 行,每行输出一个整数对的最大公约数。


数据范围


1≤n≤105,1≤ai,bi≤2×109


输入样例:


2
3 6
4 6


输出样例:


3
2


3.2思路分析

使用如上欧几里得算法。


3.3代码实现

#include <iostream>
using namespace std;
int n;
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int main(){
    cin>>n;
    while(n--){
        int a,b;
        cin>>a>>b;
        cout<<gcd(a,b)<<endl;
    }
    return 0;
}


四、快速幂

核心模板

求m^k mod p,时间复杂度O(logk)。

int qmi(int m,int k,int p){
    int res=1%p,t=m;
    while(k){
        if(k&1) res=res*t%p;
        t=t*t%p;
        k>>=1;
    }
    return res;
}


题目一

题目链接:875. 快速幂


4.1题目描述

给定 n 组 ai,bi,pi,对于每组数据,求出 aibi mod pi 的值。


输入格式


第一行包含整数 n。


接下来 n 行,每行包含三个整数 ai,bi,pi。


输出格式


对于每组数据,输出一个结果,表示 aibi mod pi 的值。


每个结果占一行。


数据范围


1≤n≤100000,1≤ai,bi,pi≤2×109


输入样例:

2
3 2 5
4 3 9


输出样例:


4
1


4.2思路分析

利用快速幂算法进行求解:首先预处理出a的次幂的结果,然后将ak拆分成这些预处理结果的组合(将k拆成2的次方的和,即k的二进制表示为1的所有2的次幂),即利用这些预处理的结果来计算ak。

6768f05cd6b84e1fc156103e2b56562a_1ea27cd5d80c4961913e9867bbaa135b.png

例子:

ee3353cc403c7202b314c9aa5c52e3e6_3713edee026847298fbf6739873dce0d.png


4.3代码实现

#include <iostream>
using namespace std;
typedef long long LL;
//快速幂,返回a^k%p的结果
int qmi(int a,int k,int p){
    LL res=1%p;         //存储结果
    while(k){         //枚举k的每位数字
        if(k&1) res=res*a%p;     //如果该位数字为1,则res乘上当前数字代表的二进制中的权重(即2的多少次幂)
        k>>=1;
        a=(LL)a*a%p;             //a每次翻倍,预处理出当前a的次幂的结果
    }
    return res;
}
int n;
int main(){
    cin>>n;
    while(n--){
        int a,k,p;
        cin>>a>>k>>p;
        cout<<qmi(a,k,p)<<endl;
    }
    return 0;
}


题目二

题目链接:876. 快速幂求逆元


4.4题目描述

给定 n 组 ai,pi,其中 pi 是质数,求 ai 模 pi 的乘法逆元,若逆元不存在则输出 impossible。


注意:请返回在 0∼p−1 之间的逆元。


乘法逆元的定义


若整数 b,m 互质,并且对于任意的整数 a,如果满足 b|a,则存在一个整数 x,使得 a / ≡ a * x(mod m),则称 x 为 b 的模 m 乘法逆元,记为 b−1 (mod m)。

b 存在乘法逆元的充要条件是 b 与模数 m 互质。当模数 m 为质数时,bm−2 即为 b 的乘法逆元。


输入格式


第一行包含整数 n。


接下来 n 行,每行包含一个数组 ai,pi,数据保证 pi 是质数。


输出格式


输出共 n 行,每组数据输出一个结果,每个结果占一行。


若 ai 模 pi的乘法逆元存在,则输出一个整数,表示逆元,否则输出 impossible。


数据范围


1≤n≤105,1≤ai,pi≤2∗109


输入样例:


3
4 3
8 5
6 3


输出样例:


1
2
impossible


4.5思路分析

由题目信息可得到以下化简。

af4057b9032bbf026d515d39f0282182_d898d4782362490c979b55327a3e3823.png

该问题就化简成了求:b * x ≡ 1 (mod p )。x即为所求的逆元。

由费马小定理可知:b^p-1 ≡ 1 (mod p )。所以我们结合上述两个式子可知,x=bp-2。

3f63f11e085f6e496806420d2a686ce9_510a2bc5e0fd4d4aa151c4b1641d2d65.png


下图内容来源:百度百科,侵删。

1ead62d7b36b3b15b42fdcf45c3ada37_31699be969074d66b3a08372d1364a7e.png

b如果是p的倍数则无解。

原因:如果p是b的倍数,那么p*x也是p的倍数,mod p之后一定等于0,不可能等于1(也就是得满足费马小定理的条件)。


4.6代码实现

#include <iostream>
using namespace std;
typedef long long LL;
//快速幂模板,返回a^k%p
int qmi(int a,int k,int p){
    LL res=1%p;
    while(k){
        if(k&1) res=res*a%p;
        k>>=1;
        a=(LL)a*a%p;
    }
    return res;
}
int n;
int main(){
    cin>>n;
    while(n--){
        int a,p;
        cin>>a>>p;
        int ans=qmi(a,p-2,p);      //ans代表所要求的逆元,即ans=a^p-2
        if(a%p) cout<<ans<<endl;   
        else cout<<"impossible"<<endl;    //无解情况:a%p=0时无解
    }
    return 0;
}
目录
相关文章
|
3月前
|
存储 安全 算法
|
3月前
|
人工智能 算法 测试技术
【数学】【排序】【C++算法】3027人员站位的方案数
【数学】【排序】【C++算法】3027人员站位的方案数
|
3月前
|
算法 测试技术 C++
【动态规划】【数学】【C++算法】1449. 数位成本和为目标值的最大数字
【动态规划】【数学】【C++算法】1449. 数位成本和为目标值的最大数字
|
3月前
|
算法 测试技术 C++
【动态规划】【 数学】C++算法:514自由之路
【动态规划】【 数学】C++算法:514自由之路
|
3月前
|
存储 算法 Serverless
【C/C++ 数据结构】深入探索数据结构中算法复杂度:从C++和数学的视角
【C/C++ 数据结构】深入探索数据结构中算法复杂度:从C++和数学的视角
56 0
|
3月前
|
算法
双指针算法(acwing)疑难讲解
双指针算法(acwing)疑难讲解
29 0
|
2月前
|
算法 Java Go
斐波那契数列是一个非常经典的数学问题,在计算机科学中也经常被用作算法设计和分析的例子。
斐波那契数列是一个非常经典的数学问题,在计算机科学中也经常被用作算法设计和分析的例子。
|
1月前
|
算法 安全 网络安全
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
|
2月前
|
存储 人工智能 算法
程序与技术分享:Acwing算法笔记
程序与技术分享:Acwing算法笔记
|
2月前
|
算法 数据挖掘 定位技术
算法必备数学基础:图论方法由浅入深实践与应用
算法必备数学基础:图论方法由浅入深实践与应用