数论是用来研究整数的性质的。
- 整数集 Z:{..−2,−1,0,1,2…}
- 自然数集N:{0,1,2,3,4…}
整除:
存在整数 k,使得a=kd,则称d|a(d 整除 a)。
- d为a的约数,a为d的倍数。
- 任何数都是0的约数。
公约数
存在一个整数d,使得d | x,d | y,则d为x,y的公约数。
最大的一个称之为最大公约数,记作gcd(x,y)。
几个推论
- 若d | a,d | b,则d | ax+by,其中a,b均为整数。
- gcd(xn,yn)=n∗gcd(x, y)
- 若n |xy 且gcd(n,x)=1,则n | y。
gcd(a,b) 为 ax+by 的最小正整数线性组合
证明:
设 s 为 ax+by 是最小正整数的线性组合
由之前的2推论可得,s|a,s|b,即gcd(a,b)<=s
① a%s=a−⌊as⌋∗s
设q=⌊as⌋
① = a−q(ax+by)=a(1−qx)+b(−qy)
因0<=a % s<s。又s为最小正整数解
所以① = a%s=0,即s | a。
同理s | b。
所以s<=gcd(a,b)。
由第一步的gcd(a,b)<=s。我们得到:
s=gcd(a,b)
素数定理
[1,N]中素数的个数约为NlgN。则从[1,N]中人选一个数,其为质数的概率为1lgN。
素数的判断
试除法:O(√n)
原理:约数成对出现(完全平方数除外)
算数基本定理
任意一个整数都能被分解为如下形式:
n=pk11pk22…pktt。其中p为质数。
t,∑ti=1ki都是logn量级的。
欧拉函数
φ(n)表示小于等于n中与n互质的数的个数
φ(n) = n\prod_{p | n}(1 - \frac{1}{p}) 其中p为质因子。
用质因子的方法,O(\sqrt{n})算出一个数的欧拉函数:
int phi = x;
for(int j = 2; j * j <= x; j++){
if(x % j == 0){
phi = phi / j * (j - 1);
while(x % j == 0) x /= j;
}
}
if(x > 1) phi = phi / x * (x - 1);
O(n)用线性筛[1, n]内所有φ值
大概长这样:
phi[1] = 1;
for(int i = 2; i <= n; i++){
if(!st[i]) primes[tot++] = i, phi[i] = i - 1;
for(int j = 0; i * primes[j] <= n; j++){
st[primes[j] * i] = true;
if(i % primes[j] == 0){
phi[primes[j] * i] = primes[j] * phi[i];
break;
}
phi[primes[j] * i] = (primes[j] - 1) * phi[i];
}
}
原理:质数p的欧拉函数为p - 1。线性递推即可。
扩展欧几里得
原理:裴蜀定理
扩展欧几里得算法可以O(loga)的时间算出:
ax + by = gcd(a, b) (a, b > 0)的一组解。
int exgcd(int a, int b, int &x, int &y){
if(b == 0){
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
原理:递推
ax + by = bx_0 + (a \% b)y_0)
已知a, b, x_0, y_0,求x, y。
= bx_0 + (a - \lfloor \frac{a}{b} \rfloor * b)y_0)
= ay_0 + b(x_0 - \lfloor \frac{a}{b} \rfloor * y_0)
通解
设d = gcd(a, b),扩展欧几里得算法求出的是ax_0 + by_0 = d,则:
- x = x_0 + k\frac{b}{d}
- y = y_0 + k\frac{a}{d}
其中k为任意整数。
x, y的分布规律可看做一条一次函数:
正整数解:x, y >= 0。
若我们想正整数解(x, y >= 0)中x的最小值,只需\% \frac{b}{d},但是C++中会膜成负数和0,所以还需要特判:
- x = (x0\ \% \frac{b}{d} + \frac{b}{d}) % \frac{b}{d}
- if\ x == 0\ then\ x += \frac{b}{d}
此时对应的y即正整数解范围内的y最大值,想判断其是否存在正整数解,只需判断对应的y > 0即可。
求y的最小值与x的最大值同理。
在正整数解内分布个数
先搞到x的最小正整数解x0,此时对应的y0 = (d - ax0) / b
那么考虑其实是可以往下等距缩,即:
cnt = \lceil y0 /\frac{a}{d} \rceil
一般套路
亦或是同余方程,还是其他玩意,你可以转化为:
ax + by = c。
此时先把d = ax + by = gcd(a, b)的x, y用扩展欧几里得算出来。
- 若c \% d \not= 0 无解
- 否则,把对应的x, y都扩大c / d倍,可以就按照刚才的来做啦。
O(n)预处理[1, n]内所有数的阶乘及其逆元
因为(i!)^{-1} = \frac{1}{i!} = \frac{i + 1}{(i+ 1)!}
所以先把infact_n算出后,得到递推公式:
infact_i = infact_{i + 1} * (i + 1)
组合数
把杨辉三角搞出来以后有一些奇怪的规律。
- 自左上(顶端)向右下一连串的和=其最右端再往下一个的值
- 一列的总和=最下端右下角的值
tql
对我这种蒟蒻实在是太有用了tqlorzstomrktxdy%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sto
棒!
强!
STO