数学知识——约数 gcd lcm

一:约数

  约数定义:约数,又称因数。整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。

1.试除法求约数:

  若d<=sqrt(n)的d是n的约数,那么n/d也一定是n的约数,就是说n的约数是成对存在的,除了sqrt(n)本身;

  因此for循环从1到n/i遍历,如果i是n的约数,则n/i也是n的约数,注意i*i=n的特殊情况。

 

  869. 试除法求约数 - AcWing题库

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 void get_divisors(int n)
 5 {
 6     vector<int>res;
 7     for(int i=1;i<=n/i;i++)
 8     {
 9         if(n%i==0)
10         {
11             res.push_back(i);
12             if(n!=i*i)res.push_back(n/i);
13         }
14     }
15     sort(res.begin(),res.end());
16     for(auto item:res)
17     {
18         printf("%d ",item);
19         //cout<<item<<" ";
20     }
21     puts("");
22 }
23 int main()
24 {
25     int n;
26     scanf("%d",&n);
27     while(n--)
28     {
29         int m;
30         scanf("%d",&m);
31         get_divisors(m);
32     }
33     
34     
35     
36     return 0;
37 }
试除法求约数

 

2.约数个数:

  公式:(a1+1)*(a2+1)*...*(ak+1)

 

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int mod=1e9+7;
 5 
 6 int main()
 7 {
 8     int n;
 9     scanf("%d",&n);
10     unordered_map<int,int>hash;
11     long long ans=1;
12     while(n--)
13     {
14         int m;
15         scanf("%d",&m);
16         for(int i=2;i<=m/i;i++)
17         {
18             while(m%i==0)
19             {
20                 m/=i;
21                 hash[i]++;
22             }
23         }
24         
25         if(m>1)hash[m]++;
26         
27     }
28     for(auto i:hash)ans=ans*(i.second+1)%mod;
29     printf("%ld",ans);
30     
31     return 0;
32 }
约数个数

 

3.约数之和:

  借助了秦九韶算法

 

 

871. 约数之和 - AcWing题库

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int mod=1e9+7;
 5 
 6 int main()
 7 {
 8     int n;
 9     scanf("%d",&n);
10     unordered_map<int,int>hash;
11     
12     while(n--)
13     {
14         int m;
15         scanf("%d",&m);
16         for(int i=2;i<=m/i;i++)
17         {
18             while(m%i==0)
19             {
20                 m/=i;
21                 hash[i]++;
22             }
23         }
24         
25         if(m>1)hash[m]++;
26         
27     }
28     
29     long long ans=1;
30     for(auto i:hash)
31     {
32         long long a=i.first,b=i.second;
33         long long t=1;
34         while(b--)t=(t*a+1)%mod;
35         ans=ans*t%mod;
36     }
37     
38     printf("%ld",ans);
39     
40     return 0;
41 }
约数之和

 

二:最大公约数gcd O(logn)

  用到了欧几里得算法(辗转相除法)

  证明gcd(a,b)==gcd(b,a%b):

    1.证明gcd(a,b)能推出gcd(b,a%b):

      假设gcd(a,b)为m,则m|a,m|b,那么m|(a*k1+b*k2),那么设k=a/b(向下取整),则m|(a-k*b),而a-k*b就是a%b的结果。得证

    2.证明gcd(b,a%b)能推出gcd(a,b):

      假设gcd(b,a%b)为m,则m|b,m|(a-k*b),那么m|(a-k*b+k*b),即m|a。得证。

  所以代码如下:

1 int gcd(int a,int b)
2 {
3     if(a%b==0)return b;
4     return gcd(b,a%b);
5 }

 

三:最小公倍数lcm

 

 

 

int lcm(int a,int b)
{
    return a*b/gcd(a,b);
}

 

posted @ 2022-02-07 19:54  wellerency  阅读(266)  评论(0编辑  收藏  举报