数学问题(数论)试除法求所有约数、约数个数、约数之和、最大公约数(欧几里得算法)

1.试除法求所有约数

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

题面:

 

代码:

 

 

#include<bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
vector<int> getdivisors(int n)//用容器来存
{
    vector<int>res;
     /*由于n/d=x,同时n/x=d也成立,所以可以得出约数是成对存在的。
        由此我们只需要枚举一下较小的的那个,即d<=n/d,把循环条件写成i<=n/i,这样时间复杂度就为O(sqrt(n))了。
    */
    for(int i=1;i<=n/i;i++)
    {
        if(n%i==0)
        {
            res.push_back(i);
            if(i!=n/i) res.push_back(n/i);//这里特判一下,如2*2=4,避免存入了两个2
        }
    }
    sort(res.begin(),res.end());//从小到大排序一下
    return res;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        auto res=getdivisors(n);
        for(auto t:res) cout<<t<<" ";
        cout<<endl;
    }
    return 0;
}

 2.约数个数

由算数基本定理可得,任何一个数可以用如下式子表示,其中Pi是质因数,ai为指数。

约数个数也可表示出来:

X=(a1+1)* (a2+1)*(a3+1)*…*(ak+1)

分析:

n的任意一个约数d,也有如下式子表示

其中0<=bi<=ai。

由于n的所有约数都可以用上式表示,且不同的Bi对应不同的约数,所以P1可以分为(a1+1)种,【(a1+1)即为0,1,2,…,a1】P2可以分为(a2+1)种…Pk可以分为(ak+1)种。综上述,约数个数为:(a1+1)* (a2+1)*(a3+1)*…*(ak+1)。

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

题面:

 代码(思路见注释):

#include<bits/stdc++.h>
#include<map>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;//有t个数
    cin>>t;
    unordered_map<int,int>primes;//用哈希表来存每个数分解出来的质因数的个数
    while(t--)//依次输入t个数
    {
        ll n;
        cin>>n;
        for(int i=2;i<=n/i;i++)//求质因数
        {
            while(n%i==0)//得到此质因数的指数
            {
                n/=i;
                primes[i]++;
            }
        }
        if(n>1) primes[n]++;//存在唯一一个大于sqrt(n)的质因子
    }
    ll ans=1;
    //遍历一遍所有质因子,约数个数就用指数+1累乘
    for(auto prime:primes) ans=ans*(prime.second+1)%mod;
    cout<<ans<<endl;
    return 0;
}

3.约数之和

由算数基本定理可得,任何一个数可以用如下式子表示,其中Pi是质因数,ai为指数。

 约数之和表示为:

 

这里就不解释了,理解一下啦。

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

题面:

 代码(思路见注释):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;//有t个数
    cin>>t;
    unordered_map<int,int>primes;//用哈希表来存每个数分解出来的质因数的个数
    while(t--)//依次输入t个数
    {
        ll n;
        cin>>n;
        for(int i=2;i<=n/i;i++)//求质因数
        {
            while(n%i==0)//得到此质因数的指数
            {
                n/=i;
                primes[i]++;
            }
        }
        if(n>1) primes[n]++;//存在唯一一个大于sqrt(n)的质因子
    }
    ll ans=1;
    //遍历一遍所有质因子,约数之和就如公式表示
    for(auto prime:primes) 
    {
        int p=prime.first,a=prime.second;
//表示其中一个质因数,b表示质因数的指数为多大
        ll t=1;
        while(a--)//依次计算pi的0次方+pi的1次方+...+pi的ai次方
        {
            t=(t*p+1)%mod;
        }
        ans=ans*t%mod;
    }
    cout<<ans<<endl;
    return 0;
}

这里提一下:

 

4.最大公约数

前提:若d能整除a,且d能整除b,则d能整除(a+b),且d能整除a、b的任意倍数之和(a*x+b*y)。

则有gcd(a,b)=gcd(b,a mod b)。[gcd为求最大公约数的函数,mod为取模]

证明:a mod b=a-c*b  (c为a/b)

      若有d/a,d/b,则有d/(a+(-c)*b),所以等式两边的集合相同,即公约数相同。

题目链接:872. 最大公约数 - AcWing题库

题面:

 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n,a,b;
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   cin>>n;
   while(n--)
   {
       cin>>a>>b;
       cout<<gcd(a,b)<<endl;
   }
    return 0;
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值