算法基础-数学知识-质数、约数

质数

埃及筛虽然用的不多,大多使用线性筛,但是埃及筛的思想很重要
在这里插入图片描述

试除法判定质数

AcWing 866. 试除法判定质数

bool isPrime(int x)
{
    
    
   if (x < 2) return false;
    for (int i = 2; i <= x / i; i ++ )//不要用开方函数或者i*i小于x。开方函数慢,i*i可能越界
        if (x % i == 0)
            return false;
    return true;
}

AcWing 867. 分解质因数

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;

void get_prime_factor(int x)
{
    
    
    for (int i = 2; i <= x / i; ++ i)
    {
    
    
        if (x % i == 0) 
        {
    
    
            cout << i << " ";
            int t = 0;
            while (x % i == 0) x /= i, t ++;
            cout << t << endl;
        }
    }

    if (x > 1) cout << x << " 1" << endl;
    cout << endl;
    return ;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n --)
    {
    
    
        int x;
        cin >> x;
        get_prime_factor(x);
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

晒质数

埃及筛

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N = 1e6 + 10;//不太记得最多多少个质数了
int primes[N];
bool st[N];
int get_prime(int x)
{
    
    
    int cnt = 0;
    for (int i = 2; i <= x; ++ i)
    {
    
    
        if (st[i]) continue;
        primes[cnt ++ ] = i;
        for (int j = i + i; j <= x; j += i)//将每个数的倍数筛掉,有倍数的一定是合数
            st[j] = true;
    }
    return cnt;
}
void solve()
{
    
    
    int x;
    cin >> x;
    cout << get_prime(x);           
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

线性筛

在埃及筛上优化了一下,每个数字只会被筛掉一次,因此是线性的

int get_prime(int x)
{
    
    
    int cnt = 0;
    for (int i = 2; i <= x; ++ i)//第一个循环和埃及筛的意义不一样
    {
    
    
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= x / i; ++ j)//不用j < cnt,因为primes[j] <= x / i的时候j一定 >= cnt
        {
    
    
            //prime[j] * i 只会会在pj * i / pj的时候被筛掉
            //因为我们保证了pj是其最小质因子
            st[primes[j] * i] = true;//每个合数分解到最后都是由一个个质数组成的
            if (i % primes[j] == 0) break;//线性筛算法精髓所在,保证primes[j]始终是每个被筛掉的数的最小质因子
        }                          
    }
    return cnt;
}

约数

试除法求约数

试除法就是枚举

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N = 1e5 + 10;
int divsors[N];
int cnt;
int get_divsors(int x)
{
    
    
    memset(divsors, 0, sizeof divsors);
    cnt = 0;
    for (int i = 1; i <= x / i; ++ i)
    {
    
    
       if (x % i == 0) 
       {
    
    
           divsors[cnt ++ ] = i;
           if (i != x / i) divsors[cnt ++] = x / i;
       }
    }
    sort(divsors, divsors + cnt);
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n -- )
    {
    
    
        int x;
        cin >> x;
        get_divsors(x);
        for (int i = 0; i < cnt; ++ i)
        {
    
    
            cout << divsors[i] << " ";
        }
        cout << endl;
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

约数个数与约数之和

在这里插入图片描述

AcWing 870. 约数个数

重点是以下
约数的意义
在这里插入图片描述
计算个数的时候为什么要加1
在这里插入图片描述

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, p = 1e9 + 7;
unordered_map<int, int> divsorts;
void get_divsors(int x)
{
    
    
    for (int i = 2; i <= x / i; ++ i)
    {
    
    
        while (x % i == 0)
        {
    
    
            divsorts[i] ++;
            x /= i;
        }
    }
    if (x > 1) divsorts[x] ++;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n --)
    {
    
    
        int x;
        cin >> x;
        get_divsors(x);
    }
    int res = 1;
    for (auto cnt : divsorts) res = (LL)res * (cnt.second + 1) % p;
    cout << res;
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

AcWing 871. 约数之和

在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, mod = 1e9 + 7;
unordered_map<int, int> divsorts;
void get_divsors(int x)
{
    
    
    for (int i = 2; i <= x / i; ++ i)
    {
    
    
        while (x % i == 0)
        {
    
    
            divsorts[i] ++;
            x /= i;
        }
    }
    if (x > 1) divsorts[x] ++ ;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n --)
    {
    
    
        int x;
        cin >> x;
        get_divsors(x);
    }
    LL res = 1;
    for (auto divsort : divsorts) 
    {
    
    
        LL t = 1;
        int a = divsort.first, b = divsort.second;
        while (b -- ) t = (t * a + 1) % mod;
        res = res * t  % mod;
    }
    cout << res;
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

欧几里德求最大公因数

求最大公因数还有一个算法就是根相减损术
A:a,B:b,D:a - m*b(a % b)
在这里插入图片描述

在这里插入图片描述
递归到最后就是 x和0的最大公约数就是x
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;

int get_max_divsort(int a, int b)
{
    
    
    if (b != 0) return get_max_divsort(b, a % b);
    else return a;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n --)
    {
    
    
        int a, b;
        cin >> a >> b;
        int res = get_max_divsort(a, b);
        cout << res << endl;
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/chirou_/article/details/132654287