数论 之 约数篇

约数

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

你可能感兴趣的:(Acm算法,算法,数据结构,c++,开发语言)