数学知识——质数、约数

数学知识——质数、约数

  • 质数
    • 试除法判定质数
    • 分解质因数
    • 筛质数
  • 约数
    • 试除法求约数
    • 约数个数
    • 约数之和
    • 最大公约数

质数

AcWing 866. 试除法判定质数

#include<iostream>
using namespace std;

int n;
bool check(int x)
{
    if(x < 2)return false;
    for(int i = 2; i <= x / i; i++)
        if(x % i == 0)return false;
    return true;
}
int main()
{
    cin >> n;
    while(n--)
    {
        int x;
        cin >> x;
        if(check(x))cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

AcWing 867. 分解质因数

#include<iostream>

using namespace std;

void broke(int n)
{
    for(int i = 2; i <= n / i; i++)//大于根号n的质因数最多只有1个
    {
        if(n % i == 0)
        {
            int cnt = 0;
            while(n % i == 0)
            {
                cnt++;
                n /= i;
            }
            cout << i << ' ' << cnt << endl;
        }
    }
    if(n > 1)cout << n << ' ' << 1 << endl;
}

int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int x;
        cin >> x;
        broke(x);
        cout << endl;
    }
    return 0;
}

AcWing 868. 筛质数

  • 知识点:线性筛质数o(n)
  • 思路:
    • 所有合数的状态(这里用st[]表示)只会被它的最小质因数更新一次
    • 若i % primes[j] != 0, 则primes[j]为i * primes[j]的最小质因数
    • 若i % primes[j] == 0,则primes[j[也为i * primes[j]的最小质因数,而此时i * primes[j+1]的最小质因数不是primes[j+1],而是primes[j],所以在i % primes[j] == 0的时候更新过程终止(即在更新i*primes[j]后跳出第二层循环)
    • 由于任意一个合数x可以表示为一个最小质因数y与另一个数z的乘积,而y < x && z < x,而st[]是从小到大来更新的,所以st[x]一定能被更新到。
#include<iostream>

using namespace std;

const int N = 1e6 + 5;

int n, primes[N], cnt;
bool st[N];

int main()
{
    cin >> n;
    for(int i = 2; i <= n; i++)
    {
        if(!st[i])primes[cnt++] = i;
        for(int j = 0; i * primes[j] <= n; j++)
        {
            st[i * primes[j]] = true;
            if(i % primes[j] == 0)break;
        }
    }
    cout << cnt;
    return 0;
}



约数

AcWing 869. 试除法求约数

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int n;

void broke(int x)
{
    vector<int>num;
    for(int i = 1; i <= x / i; i++)
    {
        if(x % i == 0)
        {
            num.push_back(i);
            if(x / i != i)
                num. push_back(x / i);
        }
    }
    sort(num.begin(), num.end());
    for(int i = 0; i < num.size(); i++)
        cout << num[i] << " ";
    cout << endl;
}
int main()
{
    cin >> n;
    while(n--)
    {
        int x;
        cin >> x;
        broke(x);
    }
    return 0;
}

AcWing 870. 约数个数

  • 核心思路:
    • 对于任意一个数x = p1a1 p2a2…pnan(p1,p2,…pn均为质数),则x的约数个数为(1+a1) * (1+a2) *… * (1+an)。
#include<iostream>
#include<unordered_map>

using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;

int n;
unordered_map<int, int>pa;

void broke(int x)
{
    for(int i = 2; i <= x / i; i++)
    {
        while(x % i == 0)
        {
            x /= i;
            pa[i]++;
        }
    }
    if(x > 1)pa[x]++;
}
int main()
{
    cin >> n;
    while(n--)
    {
        int a;
        cin >> a;
        broke(a);
    }
    
    LL ans = 1;
    for(auto t : pa)ans = ans * (t.second + 1) % mod;
    cout << ans;
    return 0;
}

AcWing 871. 约数之和

  • 核心思路:
    • 对于任意一个数x = p1a1 p2a2…pnan(p1,p2,…pn均为质数),则x的约数之和为(1+p1+p12+…+p1a1) * (1+p2+p22+…+p2a2) * … * (1+pn+pn2+…+pnan)
#include<iostream>
#include<unordered_map>

using namespace std;

typedef long long LL;
const int mod = 1e9 + 7;

int n;
unordered_map<int, int>primes;//<质因数,质因数指数>

void broke(int x)//统计质因数和其指数
{
    for(int i = 2; i <= x / i; i++)
    {
        while(x % i == 0)
        {
            x /= i;
            primes[i]++;
        }
    }
    if(x > 1)primes[x]++;
}
int main()
{
    cin >> n;
    while(n--)
    {
        int a;
        cin >> a;
        broke(a);
    }
    LL res = 1;
    for(auto prime : primes)
    {
        LL t = 1;
        int p = prime.first, q = prime.second;
        while(q--)//求和
            t = (t * p + 1) % mod;
        res = res * t % mod;
    }
    cout << res << endl;
    return 0;
}

AcWing 872. 最大公约数

//欧几里得算法(辗转相除法)
#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值