1. 数论初步
1.1欧几里得算法和唯一分解定理
欧几里得算法,也就是辗转向除法,关键在于恒等式:gcd(a,b) = gcd(b, a mod b)和边界条件gcd(a, 0) = a
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
利用gcd还可以求出两个整数a,b的最小公倍数lcm(a,b),这里引出唯一分解定理
X可以表示成若个素数相乘的形式
1.2Eratosthenes筛法
Eratosthenes筛法,就是筛法求素数
for(int i = 2; i <= n; i++)
{
if(!vis[i])
for(int j = i*i; j <=n ; j+=i)
vis[j] = 1;
}
素数定理:π(x)~x/ln(x)
π(x)表示不超过x的素数的个数
N | 1e2 | 3 | 4 | 5 | 6 | 7 | 1e8 |
π(x) | 25 | 168 | 1229 | 9592 | 78498 | 664579 | 5761455 |
x/ln(x) | 22 | 145 | 1086 | 8686 | 72382 | 620421 | 5428681 |
1.3拓展欧几里得算法
拓展欧几里得算法---找出一对数(x, y), 使得ax+by = gcd(a,b), a,b不一定是正数
边界条件:gcd(a, 0) = 1*a - 0*0 = a;
void gcd(int a, int b, int&d, int&x, int&y)
{
if(!b)
{
d = a;
x = 1;
y = 0;
}
else
{
gcd(b, a%b, d, y, x);
y-= x*(a/b);
}
}
可以用于求整数方程,直线方程等
1.4 同余与模算术
(a+b)mod n = ((a mod n) + (b mod n))mod n;
(a- b)mod n = ((a mod n) - (b mod n) + n) mod n;
ab mod n = (a mod n)(b mod n)mod n;
减法需要注意a mod n 小于 b mod n
乘法注意a mod n 和 b mod n 相乘可能会溢出,中间结果需要开更大的数据类型
幂取模
int pow_mod(int a, int n, int m)
{
if(n == 0) return 1;
int x = pow_mod(a, n/2, m);
long long ans = (long long)x * x % m;
if(n % 2 == 1) ans = ans * a % m;
return (int) ans;
}
用了分治加速
方程ax = 1(mod n) 的解称为a关于模n的逆。当gcd(a,n) = 1时,方程有x的唯一解,否则方程无解
几道练习题
Colossal Fibonacci Numbers! - UVA 11582 - Virtual Judge
Disgruntled Judge - UVA 12169 - Virtual Judge
Choose and divide - UVA 10375 - Virtual Judge