试除法求约数个数

155 阅读1分钟

870. 约数个数 - AcWing题库

根据算数基本定理,一个数可以由若干个质因子的乘积组成。公式如下:

image.png

求约数个数的公式:

image.png

我们可以发现求约数个数的公式是其所有约数的指数+1相乘得到的。

验证:

以12举例,12=22+3112 = 2^{2} + 3^{1}

12的约数有1, 2, 3, 4, 6, 12

约数个数:2+11+1=6(2 + 1) * (1 + 1) = 6,相当于求每个约数的组合个数,前面有三种可能,20=12^{0} = 1, 21=22^{1} = 2 ,22=4 2^{2} = 4 ,后面有两种可能,30=1,31=3 3^{0} = 1 , 3^{1} = 3 。将前面三种可能和后面两种可能进行排列组合,总共有2 * 3种可能。

证明

求约数之和的公式:

image.png

约数之和: 相当于对约数个数的每种可能取出,进行相加,得到所有约数的和。

验证:

解:将360分解质因数可得

360=233251360=2^3*3^2*5^1

由约数和定理可知,360所有正约数的和为

(20+21+22+23)×(30+31+32)×(50+51)=(1+2+4+8)(1+3+9)(1+5)=15×13×6=1170(2^0+2^1+2^2+2^3)×(3^0+3^1+3^2)×(5^0+5^1)=(1+2+4+8)(1+3+9)(1+5)=15×13×6=1170

证明

code

#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
unordered_map<int,int>h;
 long long res;
int solve(int n)
{
    for(int i=2;i*i<=n;i++)
    {
      while(n%i==0)  //i能整除n,说明i是n的约数
      {
          h[i]++;    //统计一下约数的个数,即指数个数
          n/=i;      //把i除尽
      }
    }
    if(n>1)h[n]++;  //最后一个约数
    
    res=1;
    for(auto it=h.begin();it!=h.end();it++)
    {
        //套用求约数个数的公式
        res=res*(it->second+1)%MOD;
    }
   return res;
}
int main()
{
    int n;cin>>n;
    while(n--)
    {
        int x;cin>>x;
        solve(x);
    }
     cout<<res<<endl;
    return 0;
}