约数
约数
什么是约数
约数,又称之为因数。整数\(a\)除以整数\(b(b!=0)\)除得的商正好是整数而没有余数。我们就说\(a\)能被\(b\)整除,或\(b\)能整除\(a\)。\(a\)称为\(b\)的倍数,\(b\)称为\(a\)的约数。
约数的相关运算
求一个数的所有约数
用试除法枚举,时间复杂度\(O(\sqrt n)\)。
void Divisor(int n){
int t;
for(int i = 1; i <= sqrt(n); i++){
if(n % i == 0) cout << i << " ";
}
int res = sqrt(n);
if(res * res == n) t = res - 1;
else t = res;
for(int i = t; i >= 1; i--){
if(n % i == 0) cout << n/i << " ";
}
}
如何求约数个数
我们都知道,每一个合数都可以写成几个素数相乘的形式,其中每个素数都是这个合数的因数。所以我们就可以把\(n\)分解成:\(n=p_1^{a_1}\times p_2^{a_2}\times \dots \times p_k^{a_k}\),其中\(p_1,p_2,\dots,p_k\)是不同的素数,\(a_1,a_2,\dots,a_k\)是正整数。
由约数定义可知\(p_1^{a_1}\)的约数有:\(p_1^0, p_1^1, p_1^2,....p_1^{a_1}\),共\((a_1+1)\)个;同理\(p_2^{a_2}\)的约数有\((a_2+1)\)个,\(\dots\),\(p_k^{a_k}\)的约数有\((a_k+1)\)个。
故根据乘法原理:\(n\)的正约数的个数为\(\prod_{i = 0}^n(a_i+1)=(a_1+1)\times(a_2+1)\times\dots\times(a_n+1)\)。
void NumDivisor(int n){
map<int,int>ma;
map<int,int>::iterator iter;
ll res = 1;
for(int i = 2; i <= n / i; i++){
while(n % i == 0){
n /= i;
ma[i]++;
}
}
if(n > 1) ma[n]++;
for(iter = ma.begin(); iter != ma.end(); iter++){
res = res * (iter->second + 1);
}
cout << res;
}
最大公约数
轻点一下有惊喜。
如何求约数和
由约数定义我们可知\(p_1^{a_1}\)的约数有:\(p_1^0, p_1^1, p_1^2,....p_1^{a_1}\),共\((a_1+1)\)个;同理\(p_2^{a_2}\)的约数有\((a_2+1)\)个,\(\dots\),\(p_k^{a_k}\)的约数有\((a_k+1)\)个。而实际上\(n\)的约数是在\(p_1^{a_1},p_2^{a_2},\dots,p_k^{a_k}\)每个约数中分别挑选一个相乘得来,这样可知共有\((a_1+1)\times(a_2+1)\times\dots\times(a_k+1)\)种挑法,即约数的个数,有乘法原则我们可知它们的和为:\(f(n)=(p_1^0+p_1^1+p_1^2+…p_1^{a_1})\times(p_2^0+p_2^1+p_2^2+…p_2^{a_2})…(p_k^0+p_k^1+p_k^2+…p_k^{a_k})\)。
ll fastpow(int a, int n){
ll res = 1;
while(n){
if(n & 1) res = res * a;
a = a * a;
n >>= 1;
}
return res;
}
void SumDivisor(int n){
ll res = 0, ans = 1;
map<int,int>ma;
map<int,int>::iterator iter;
for(int i = 2; i <= n / i; i++){
while(n % i == 0){
n /= i;
ma[i]++;
}
}
if(n > 1) ma[n]++;
for(iter = ma.begin(); iter != ma.end(); iter++){
res = 0;
for(int i = 0; i <= iter->second; i++){
res = (res + fastpow(iter->first,i));
}
ans = ans * res;
}
cout << ans;
}