约数篇
定义
若整数n除以整数d的余数为0,即d能整除n,则称d为n的约数。记为
●求N的正约数集合
除了完全平方数以外,n的约数都会成对出现。即
for(int i = 2; i <= sqrt(n); i++) {
if(n % i == 0) {
factor[++m] = i;
if(n/i != i) factor[++m] = n / i;
}
}
●求1~N每个数的正约数集合
若把每个数的正约数用试除法求出,复杂度过高。可以反过来考虑,对于每个数
vector<int> factor[N];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n/i; j++) {
//依然是防爆int的写法
factor[i*j].push_back(i);
}
}
●最大公约数
定义
- 若
d|a 且d|b , 则称d 为a,b 的公约数。使得d 最大,则d 为a,b 的最大公约数。 - 若
m 同时为a 和b 的倍数,则称m 为a,b 的公倍数,使得m 最小,则m 为a, b 的最小公倍数。
定理
-
∀a,b \in N, a \geq b$, 有 $gcd(a,b) = gcd(b, a-b) = gcd(a, a-b) -
∀a,b \in N$, 有$gcd(2a, 2b) = 2gcd(a,b) -
∀a,b \in N$, $gcd(a,b) * lcm(a,b) = a * b
显然都成立
欧几里得算法
根据第一条,可以得出。
证明可用容斥原理。对于质因子p,1~N中含p的有
类似的,我们可以对全部质因子进行一次容斥,最后得出式子如上。
根据欧拉函数计算公式,套在质因数分解里就可以了。
int phi(int n) {
int ans = n;
for(int i = 2; i <= sqrt(n); i++) {
if(n % i == 0) {
ans = ans / i * (i-1);
while(n % i == 0) n /= i
}
}
if(n > 1) ans = ans / n * (n-1);
return ans;
}
性质过多,有点超noip。