约数个数和约数之和
约数个数
一个数a的约数个数
a = p1a1 x p2a2 x p3a3 ... pkak
p1 p2 p3 ... pk 都是a中的质因数,a1 a2 a3 就是其中的p1 p2 p3 的个数。
所以约数个数为一个排列组合:
可以在 p1 中选择 0 ~ a1 任意个数,
在 p2 中选择 0 ~ a2 任意个数,
在 p3 中选择 0 ~ a3 任意个数,然后他们的乘积,就是a 的约数
所以约数的个数 = (a1+1)x(a2+1)x (a3+1)... x(ak+1)
代码:
#include <iostream>
#include <map>//unordered_map会快很多,因为它的插入是O(1)的时间复杂度
using namespace std;
typedef long long ll;
map<int,ll> mp;
const ll mod = 1e9+7;
int main(){
int n;
cin>>n;
int x;
for(int i=0;i<n;i++){
cin>>x;
for(int j=2;j*j<=x;j++){
int num=0;
while(x%j==0){
x/=j;
num++;
}
mp[j]+=num;
}
if(x>1) mp[x]++;
}
ll ans=1;
for(auto it=mp.begin();it!=mp.end();it++){
ans=(ans*(1+it->second))%mod;
}
cout<<ans;
return 0;
}
约数之和
同理
a = p1a1 x p2a2 x p3a3 ... pkak
所以a的约数为
p10 x p20 ... x pk0 +
p10 x p20 ... x pk1
...
所以约数之和 = (p10 +p11+...p1a1)x (p20 +p21+...p2a2)... (pk0 +pk1+...pkak)
相当于从每个括号里选一个数
ac代码:
#include <iostream>
#include <unordered_map>
using namespace std;
typedef long long ll;
unordered_map<int,ll> mp;
const ll mod = 1e9+7;
int main(){
int n;
cin>>n;
int x;
for(int i=0;i<n;i++){
cin>>x;
for(int j=2;j*j<=x;j++){
int num=0;
while(x%j==0){
x/=j;
num++;
}
mp[j]+=num;
}
if(x>1) mp[x]++;
}
ll ans=1;
for(auto it=mp.begin();it!=mp.end();it++){
ll p=it->first,a=it->second;
ll t=1;
while(a--)
t=(t*p+1)%mod;
ans=(ans*t)%mod;
}
cout<<ans;
return 0;
}