数论基础:
整除
定义:a除以非0整数b商为整数,且余数为零,我们就说a能被b整除或说b能整除a,记作b|a。
可整除性的基本性质或特征如下:
- 若a|b, a|c, 则a|(b+c)
- 若a|b, 那么对所有整数c, a|bc
- 若a|b, b|c, 则a|c (传递性)
- 1 是任何整数的约数,即对于任何整数a,总有1|a
- 0 是任何非零整数的倍数,a≠0,a为整数,则a|0
整除关系具有传递性。
素数
- 因子仅有 1 和其本身 。
- 任何合数都可以写成素数乘积的形式。
约数
试除法求所有约数代码如下:
朴素想法是直接枚举1-n,如果n%i==0,i就是约数,但是考虑到约数是成对出现的,假设i是n的约数,那么n/i也是n的约数,所以只需要枚举到sqrt(n)即可
vector<int> get_divisors(int x){
vector<int> res;
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0){
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(), res.end());
return res;
}
约数个数和约数之和:
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
求约数个数代码如下:
for (int i = 2; i <= x / i; i++){
while (x%i == 0) //i为约数
{
x /= i;
primes[i]++; //统计每个约数的个数
}
}
if (x > 1) primes[x]++; //如果还没分解清,说明剩下的这个数是它的因数且只有一个
}
long long res = 1;
for (auto prime : primes){
res = res * (prime.second + 1) % mod;//约数个数=(a1+1)(a2+1)...(ak+1)
}
cout << res << endl;
return 0;
}
求最大公约数代码如下: 辗转相除法,gcd(a,b)=gcd(b,a%b)(规定0可以整除任何数)
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
注:以下是讲课人上课讲的笔记