约数
什么是约数
约数,又称之为因数。整数 a a a除以整数 b ( b ! = 0 ) b(b!=0) b(b!=0)除得的商正好是整数而没有余数。我们就说 a a a能被 b b b整除,或 b b b能整除 a a a。 a a a称为 b b b的倍数, b b b称为 a a a的约数。
约数的相关运算
求一个数的所有约数
用试除法枚举,时间复杂度 O ( n ) O(\sqrt n) O(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 n分解成: n = p 1 a 1 × p 2 a 2 × ⋯ × p k a k n=p_1^{a_1}\times p_2^{a_2}\times \dots \times p_k^{a_k} n=p1a1×p2a2×⋯×pkak,其中 p 1 , p 2 , … , p k p_1,p_2,\dots,p_k p1,p2,…,pk是不同的素数, a 1 , a 2 , … , a k a_1,a_2,\dots,a_k a1,a2,…,ak是正整数。
由约数定义可知 p 1 a 1 p_1^{a_1} p1a1的约数有: p 1 0 , p 1 1 , p 1 2 , . . . . p 1 a 1 p_1^0, p_1^1, p_1^2,....p_1^{a_1} p10,p11,p12,....p1a1,共 ( a 1 + 1 ) (a_1+1) (a1+1)个;同理 p 2 a 2 p_2^{a_2} p2a2的约数有 ( a 2 + 1 ) (a_2+1) (a2+1)个, … \dots …, p k a k p_k^{a_k} pkak的约数有 ( a k + 1 ) (a_k+1) (ak+1)个。
故根据乘法原理: n n n的正约数的个数为 ∏ i = 0 n ( a i + 1 ) = ( a 1 + 1 ) × ( a 2 + 1 ) × ⋯ × ( a n + 1 ) \prod_{i = 0}^n(a_i+1)=(a_1+1)\times(a_2+1)\times\dots\times(a_n+1) ∏i=0n(ai+1)=(a1+1)×(a2+1)×⋯×(an+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^{a_1} p1a1的约数有: p 1 0 , p 1 1 , p 1 2 , . . . . p 1 a 1 p_1^0, p_1^1, p_1^2,....p_1^{a_1} p10,p11,p12,....p1a1,共 ( a 1 + 1 ) (a_1+1) (a1+1)个;同理 p 2 a 2 p_2^{a_2} p2a2的约数有 ( a 2 + 1 ) (a_2+1) (a2+1)个, … \dots …, p k a k p_k^{a_k} pkak的约数有 ( a k + 1 ) (a_k+1) (ak+1)个。而实际上 n n n的约数是在 p 1 a 1 , p 2 a 2 , … , p k a k p_1^{a_1},p_2^{a_2},\dots,p_k^{a_k} p1a1,p2a2,…,pkak每个约数中分别挑选一个相乘得来,这样可知共有 ( a 1 + 1 ) × ( a 2 + 1 ) × ⋯ × ( a k + 1 ) (a_1+1)\times(a_2+1)\times\dots\times(a_k+1) (a1+1)×(a2+1)×⋯×(ak+1)种挑法,即约数的个数,有乘法原则我们可知它们的和为: f ( n ) = ( p 1 0 + p 1 1 + p 1 2 + … p 1 a 1 ) × ( 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 ) 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}) f(n)=(p10+p11+p12+…p1a1)×(p20+p21+p22+…p2a2)…(pk0+pk1+pk2+…pkak)。
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;
}
1482

被折叠的 条评论
为什么被折叠?



