数论之约数

试除法求约数

在这里插入图片描述
题目大意:输出n个数,分别输出这n个数所有的约数

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

using namespace std;

const int N = 1e5 + 10;

vector<int> solve (int n){
    vector<int> a;
    // 当i是约数,那么n/i必定也是约数
    for (int i = 1; i <= n/i; i ++){
        if (n%i == 0){
            a.push_back(i);
            // 当i!= n/i 把n/i读入
            if (n/i != i)
                a.push_back(n/i);
        }
    }
    sort (a.begin(),a.end());
    return a;
}


int main(){
    int n;
    cin >> n;
    int num;
    while (n --){
        cin >> num;
        auto t = solve(num);
        ///for(auto x : arr) 遍历方式, x只是将arr里的元素复制下来,改变x不会改变arr的元素
        //for(auto &x : arr)  x是将arr元素的地址拿出来,改变x会改变arr的元素
        for (auto x : t)
            printf("%d ",x);
        puts("");
    }
}

约数的个数

基于算术基本定理

N = (p1x1)(p2x2)(p3x3)…(pkxk)
约数个数=(x1+1)(x2+1)(x3+1)…(xk+1)
注意,这里的p1…pi是指质因子
例子
24=2223=2³3
再用各个质数的指数加一后再相乘即为此数的约数个数,
比如 (3+1)(1+1)=42=8, 即表示24有8个约数。
24的约数:1、2、3、4、6、8、12、24

思路就是先把原数分解为质因数,最后把每一个数的指数累加即可。从a1一直分解到an,由于a的数据过大,此处用哈希表进行存储。
题目:求n个数的乘积的约数个数
因此不能乘起来再求,这里用哈希表存一下质因子和其指数,用相应的公式求解

# include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;

int main(){
    int n , x;
    unordered_map<int,int> hash;
    cin >> n;
    while (n --){
        cin >> x;
        for (int i = 2; i <= x/i; i ++){
            while (x%i==0){
                hash[i] ++;
                x/=i;
            }
        }
        // x最大公约数可能大于sqrt(x),将剩余的质因数读取进去
        if (x > 1) hash[x] ++;
    }
    ll ans = 1;
    for (auto i : hash) ans = ans * (1 + i.second) %mod;
    cout << ans;
    return 0;
}

约数之和

在这里插入图片描述
这里的约数个数约数之和 这两个公式是建立在质因字的前提下

题目:求n个数的乘积的约数之和 同上题一样


# include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;

int main(){
    int n,x;
    unordered_map<int,int> hash;
    cin >> n;
    while (n --){
        cin >> x;
        for (int i = 2; i <= x/i; i ++){
            while (x%i == 0){
                x /= i;
                hash[i] ++;
            }
        }
        if (x > 1) hash[x] ++;
    }
    
    ll ans = 1;

    for (auto i: hash){
        ll a = i.first;
        ll b = i.second;
        ll t= 1;
        while (b --){
            t = (t*a + 1) % mod; 
        }
        ans = ans * t % mod;
    }
    
    cout << ans;
    return 0;
}

完全平方数

题目: acwing3491

题意 : 输出一个数a, 让你求出一个最小的数b,使得a*b是某数的平方

思路: 求出a的所有质因数及其质因数的指数,那么ans就是指数为奇数的质因数的乘积

代码

# include <iostream>
# include <unordered_map>
# include <string>
# include <algorithm>

using namespace std;

typedef long long ll;

int main(){
    ll n;
    ll ans = 1;
    cin >> n;
    unordered_map<ll,ll> hash;
    
    for (ll i = 2; i <= n/i; i ++){
        while (n%i == 0){
            n/=i;
            hash[i] ++;
        }
    }
    
    if(n > 1) hash[n] ++;
    
    for (auto i : hash){
        if (i.second%2)
            ans *= i.first;
    }
    
    cout << ans;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值