数论

一、错排

考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。

求错排个数:D(n) = (n-1) [D(n-2) + D(n-1)]

详细:错排

二、卡特兰数

三、期望概率

期望可加性:

若满足 P(a, b) = P(a) * P(b),则有E(a, b) = E(a) + E(b)

四、逆元(inv)

前言:

给定正整数m,若用m除以两个整数a和b所得余数相同,称a和b对模m同余,记作a ∗ b ≡ 1(mod m)

1、什么是逆元

举个栗子:假设要计算(a / b) % m,而b非常大,这里我们就可以把(a / b) 转化为(a * inv(b))

但是我们不能直接说一个数的逆元是多少,只能说一个数a在模p的条件下的逆元是多少

这里有个结论:当且仅当a与p互质时,a关于p的逆元存在

证明:
a * b ≡ 1(mod m)化简一下得到a * b + b * p = 1

假设a p不互质,则存在公约数d = gcd(a, p) > 1

原式中提出d得到:d * (a * b / d + b * p / d) = 1

移项:(a * b / d + b * p / d) = 1 / d

易知a, p能整除d,所以括号内定为整数,又因为d > 1,等式右边必为真分数,等式无解,因此a一定与p互质

五、gcd与拓展gcd

1、gcd(最大公约数)

#include 
using namespace std;
int gcd(int a, int b) {
	if(a < b) swap(a, b);
	if(b == 0) return a;
	return gcd(b, a % b);
}
int main() {
	int n, m;
	cin >> n >> m;
	cout << gcd(n, m);
} 

2、拓展gcd

#include 
using namespace std;
int x, y, q;
void exgcd(int a, int b) {
	if(b == 0) {
		x = 1;
		y = 0;//如果gcd中有一项为0,则最大公约数为另一个不为0的数,并且只有唯一解 
		q = a;
	}
	else {
		exgcd(b, a % b);//gcd(a, b) = gcd(b, a % b);
		int temp = x;
		x = y;
        y = temp - a / b * y;
 	}
}
int main() {
	int a, b;
	cin >> a >> b;
	if(a < b) swap(a, b);
	exgcd(a, b);
	printf("%d = %d * %d + %d * %d", q, a, x, b, y);
	return 0;
}
//求gcd(a, b) = a * x + b * y的解 

证明:

ax1 + by1 = bx2 + (a % b)y2;

因为a % b = a - (a / b) * b;

所以原式转化为:ax1 + by1 = bx2 + (a - (a / b) * b)y2;

拆开右式:bx2 + ay2 - (a / b) * by2;

因此:ax1 + by1 = ay2 + bx2 - (a / b) * by2 = ay2 - b(x2 - (a / b) * b);

根据恒等式:x1 = y2; y1 = x2 - (a / b) * b;

你可能感兴趣的:(数论,数论)