数论 之 约数篇

约数

1) 试除法求约数

原题链接:869. 试除法求约数 - AcWing题库

思路:与上面的试除法求质数很相似 a|b的意思是,b%a = 0

如果x|n 那么一定有(n/x)|n,所以,著需要求一个,另一个直接能得到

核心代码:

 for(int i=1;i<=n/i;i++){
            if(n%i==0){
                a.push_back(i);
                if(n/i!=i)a.push_back(n/i);
            }
        }

完整代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace  std;
vector<int>a;
int main(){
    
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        a.clear();
        for(int i=1;i<=n/i;i++){
            if(n%i==0){
                a.push_back(i);
                if(n/i!=i)a.push_back(n/i);
            }
        }
        sort(a.begin(),a.end());
        for(int x:a)cout<<x<<' ';
        cout<<endl;
    }
    return 0;
}

2) 约数个数

原题链接:870. 约数个数 - AcWing题库

公式:假设一个数的质因数为 p1^a1 , p2^a2, p3^a3, … pk^ak

pi为质因数,ai为这个质因数的次数

那么约数个数 sum = (a1+1) * (a2+2) * … *(ak+k);

证明:严格推导有点麻烦,我在这就举个例子 假设

有一个数的质因数序列为 p1^1 , p2^2

那么 这个数的约数可能为 p1^0 * p2^0 , p1^0 * p2^1 , p1^0 * p2^2 , p1^1* p2^0 , p1^1 * p2^1 , p1^1* p2^2

相信看到这到这的小伙伴已经找到规律了 就是每一个质因数的次数+1然后相乘

至于为什么要+1 ,也很简答,因为是从0次方开始的

核心代码:

unordered_map<int,int>mp;
       for(int i=2;i<=n/i;i++){
         
               while(n%i==0){
                   n/=i;
                   mp[i]++;
               }
       }
       if(n>1)  mp[n]++;
    }
   int sum = 1;
  for(auto x:mp)sum = sum%mod*(x.second+1);

完整代码

#include<iostream>
#include<unordered_map>
#define int long long
using namespace std;

int mod = 1e9+7;
unordered_map<int,int>mp;
signed main(){
    int t;
    cin>>t;
      int j = 0;
    while(t--){
        int n;
        cin>>n;
      
       for(int i=2;i<=n/i;i++){
         
               while(n%i==0){
                   n/=i;
                   mp[i]++;
               }
       }
       
       if(n>1)  mp[n]++;
      
    }
   int sum = 1;
  for(auto x:mp)sum = sum%mod*(x.second+1);
   cout<<sum%mod<<endl;
      
       
    return 0;
}

3)约数和

原题链接:871. 约数之和 - AcWing题库

公式:假设一个数的质因数为 p1^a1 , p2^a2, p3^a3, … pk^ak

pi为质因数,ai为这个质因数的次数

那么约数和 sum = (p1^0 + p1^1+… p1^a1) * (p2^0 + p2^1 +…) * … *(pk^0 + pk^1+ …+pk^ak);

证明:由约数的个数公式推导而来,还是那个例子

有一个数的质因数序列为 p1^1 , p2^2

那么 这个数的约数可能为 p1^0 * p2^0 , p1^0 * p2^1 , p1^0 * p2^2 , p1^1* p2^0 , p1^1 * p2^1 , p1^1* p2^2

那么我们合并同类项发现等于 sum = p1^0 *(p2^0 + p2^1 + p2^2) + p1^1 *(p2^0 + p2^1 + p2^2) = (p1^0 + p1^1) * ( p2^0 + p2^1 + p2^2)

完整代码:

#include<iostream>
#include<unordered_map>
#define int long long
using namespace std;

int mod = 1e9+7;
unordered_map<int,int>mp;
signed main(){
    int t;
    cin>>t;
      int j = 0;
    while(t--){
        int n;
        cin>>n;
      
       for(int i=2;i<=n/i;i++){
         
               while(n%i==0){
                   n/=i;
                   mp[i]++;
               }
       }
       
       if(n>1)  mp[n]++;
      
    }
   int sum = 1;
  for(auto x:mp){
     int t=x.first+1;
     for(int i=1;i<x.second;i++)t = t%mod*x.first%mod+1;
     sum = sum%mod*t%mod;
  }
   cout<<sum%mod<<endl;
      
       
    return 0;
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海风许愿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值