1、求一个数的所有约数
使用试除法,如果 n 能整除 d, 则 n 也能整除 n / d,所以只需要遍历1~ n \sqrt{n} n即可获得所有约数
vector<int> ans;
for(int i = 1; i <= n / i; i ++)
{
if(n % i == 0)
{
ans.push_back(i);
if(i != n / i) ans.push_back(n / i);
}
}
2、求一个数所有约数的个数
首先将数N分解质因数为
p
1
k
1
p
2
k
2
p
3
k
3
.
.
.
p
n
k
n
p_1^{k_1}p_2^{k_2}p_3^{k_3}...p_n^{k_n}
p1k1p2k2p3k3...pnkn
对于N的每个约数都可以写成
p
1
b
1
p
2
b
2
p
3
b
3
.
.
.
p
n
b
n
p_1^{b_1}p_2^{b_2}p_3^{b_3}...p_n^{b_n}
p1b1p2b2p3b3...pnbn,通过变换
b
1
b_1
b1到
b
n
b_n
bn的数值,就可以变成不同的约数。
所以所有约数的数量就是所有
b
1
b
2
b
3
b
4
.
.
.
b
n
b_1b_2b_3b_4...b_n
b1b2b3b4...bn的不同组合的数量。其中
b
1
b_1
b1的取值范围为0到
k
1
k_1
k1,
b
2
b_2
b2为0到
k
2
k_2
k2,以此类推。
所有所有约数的数量K =
(
k
1
+
1
)
(
k
2
+
1
)
.
.
.
(
k
n
+
1
)
(k_1 + 1)(k_2 + 1)...(k_n + 1)
(k1+1)(k2+1)...(kn+1)
unordered_map<int,int> mp;
for(int i = 2; i <= n / i; i ++ )
{
if(n % i == 0)
{
while(n % i == 0)
{
n /= i;
mp[i] ++;
}
}
if(n > 1) mp[n] ++;
}
long long res = 1;
for(auto p : mp)
{
res = res * (1 + p.second);
}
3、求一个数的所有约数之和
首先将数N分解质因数为
p
1
k
1
p
2
k
2
p
3
k
3
.
.
.
p
n
k
n
p_1^{k_1}p_2^{k_2}p_3^{k_3}...p_n^{k_n}
p1k1p2k2p3k3...pnkn
对于N的每个约数都可以写成
p
1
b
1
p
2
b
2
p
3
b
3
.
.
.
p
n
b
n
p_1^{b_1}p_2^{b_2}p_3^{b_3}...p_n^{b_n}
p1b1p2b2p3b3...pnbn,通过变换
b
1
b_1
b1到
b
n
b_n
bn的数值,就可以变成不同的约数
在此之上,其实求和SUM就是求
∑
0
k
1
∑
0
k
2
∑
0
k
3
.
.
.
∑
0
k
n
p
1
b
1
p
2
b
2
p
3
b
3
.
.
.
p
n
b
n
\sum_0^{k1}\sum_0^{k2}\sum_0^{k3}...\sum_0^{kn}p_1^{b_1}p_2^{b_2}p_3^{b_3}...p_n^{b_n}
0∑k10∑k20∑k3...0∑knp1b1p2b2p3b3...pnbn整理后得到
(
p
1
0
+
p
1
1
+
p
1
2
+
p
1
3
+
.
.
.
p
1
k
1
)
(
p
2
0
+
p
2
1
+
p
2
2
+
p
2
3
+
.
.
.
p
2
k
1
)
.
.
.
(
p
n
0
+
p
n
1
+
p
n
2
+
p
n
3
+
.
.
.
p
n
k
1
)
(p_1^0 + p_1^{1} + p_1^{2}+ p_1^{3}+...p_1^{k_1})(p_2^0 + p_2^{1} + p_2^{2}+ p_2^{3}+...p_2^{k_1})...(p_n^0 + p_n^{1} + p_n^{2}+ p_n^{3}+...p_n^{k_1})
(p10+p11+p12+p13+...p1k1)(p20+p21+p22+p23+...p2k1)...(pn0+pn1+pn2+pn3+...pnk1)
unordered_map<int,int> mp;
for(int i = 2; i <= n / i; i ++ )
{
if(n % i == 0)
{
while(n % i == 0)
{
n /= i;
mp[i] ++;
}
}
if(n > 1) mp[n] ++;
}
long long res = 1;
for(auto p : mp)
{
long long sum = 1;
for(int i = 0; i < p.second; i ++)
{
sum = sum * p.first + 1;
}
res = res * sum;
}
4、最大公因数
给定两个数a、b求两个数的最大公因数
设两个正整数 a 和 b 的 最大公约数 d,则有 gcd(a,b) = gcd(b,a%b)
证明:
设a%b = a - k*b 其中k = a/b(向下取整)
- 若d是(a,b)的公约数 则知 d|a 且 d|b 则易知 d|a-k*b 故d也是(b,a%b) 的公约数
- 若d是(b,a%b)的公约数 则知 d|b 且 d|a-kb 则 d|a-kb+k*b = d|a 故而d|b 故而 d也是(a,b)的公约数
因此(a,b)的公约数集合和(b,a%b)的公约数集合相同 所以他们的最大公约数也相同
资料来源
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}