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

这里写目录标题

  • 质数
    • 试除法判定质数
    • 晒质数
      • 埃及筛
      • 线性筛
  • 约数
    • 试除法求约数
    • 约数个数与约数之和
      • AcWing 870. 约数个数
      • AcWing 871. 约数之和
    • 欧几里德求最大公因数

质数

埃及筛虽然用的不多,大多使用线性筛,但是埃及筛的思想很重要

试除法判定质数

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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}

约数个数与约数之和

算法基础-数学知识-质数、约数_第1张图片

AcWing 870. 约数个数

重点是以下
约数的意义
算法基础-数学知识-质数、约数_第2张图片
计算个数的时候为什么要加1
算法基础-数学知识-质数、约数_第3张图片

 #include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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. 约数之和

算法基础-数学知识-质数、约数_第4张图片

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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)
算法基础-数学知识-质数、约数_第5张图片

算法基础-数学知识-质数、约数_第6张图片
递归到最后就是 x和0的最大公约数就是x
算法基础-数学知识-质数、约数_第7张图片

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(算法,c++,蓝桥杯,数学)