基础数论

快速乘法

(a*b)%p = (a%p)(b%p)%p
如果模较大,a%p * b%p 可能会超出long long 的范围可以使用快速乘法

ll fastMul(ll a, ll b, ll p) {
     
	a %= p;
	ll ans = 0;
	while(b > 0) {
     
		if(b & 1) ans = (ans + a) % p;
		b >>= 1;
		a = (a + a) % p;
	}
	return ans;
} 

逆元
a/b%c = ab^-1%c
如果c是素数,有下面定理
费马小定理:设b是一个整数,c是一个素数,二者互质,那么b^c-1 =1(modc)
改写一下 bb^c-2 = 1(modc)
所以取b^-1 = b^c-2即可

最大公因数

ll gcd(ll a, ll b) {
     
	return b ? gcd(b, a % b) : a;
}

最小公倍数

ll lcm (ll a, ll b) {
     
	return a / gcd(a, b) * b;
}

扩展欧几里得算法

求ax + by = c的解
1、上述方程有解的充要条件是c 是gcd(a, b) 的倍数
2、所有解为:x = c / d * x0 + b / d * t, y = c / d * y0 - a / d * t

int extgcd(int a, int b, int& x, int& y) {
     
	int d = a;
	if(b != 0) {
     
		d = extgcd(b, a % b, y, x);
		y -= (a / b) * x;
	}else {
     
		x = 1;
		y = 0;
	}
	return d;
}

扩展欧几里得求逆元
求·b^-1 使得 b*b^-1 = 1(mod c),实质上是求解方程bx + cy = 1中的x,可以用欧几里得算法求解。

素数的判断

bool isPrime(ll n) {
     
	if(n == 1) return false;
	for(ll i = 2; i * i <= n; i++) {
     
		if(n % i == 0) return false;
		return true;
	}
}

埃氏筛:复杂度O(NlgN)

void getPrime(bool p[], int n) {
     
	for(int i = 1; i <= n; i++) p[i] = true;
	p[1] = false;
	for(int i = 2; i <= n; i++) {
     
		if(p[i]) {
     
			for(int j = i + i; j <= n; j += i) p[j] = false;
		}
	}
}

用下面的方法可以保证每个合数只被它最下的素因子筛掉一遍:复杂度O(N)

ll getPrime(ll n, bool vis[], ll prime[]) {
     
	ll tot = 0;
	for(ll i = 1; i <= n; i++) vis[i] = 0;
	for(ll i = 2; i <= n; i++) {
     
		if(!vis[i]) prime[tot++] = i;
		for(ll j = 0; j < tot; j++) {
     
			if(prime[j] * i > n) break;
			vis[prime[j] * i] = 1;
			if(i % prime[j] == 0) break;
		}
	}
	return tot;
}

组合数取余

求组合数,如果n, m不大,可以开O(N^2)的空间,利用杨辉恒等式来预处理组合数表

const ll mo = 1e9 + 7;
ll c[1005][1005];
void getC(int n) {
     
	for(int i = 0; i <= n; i++) {
     
		for(int j = 0; j <= i; j++) {
     
			if(j == 0 || j == i) c[i][j] = 1;
			else c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
		}
	}
}

在竞赛中,常常需要计算组合数取余,如果n, m很小可以用C++的库函数 double tgamma(double x)

#include
ll C(ll n, ll m) {
     
	return (ll)round(tgamma(n + 1) / tgamma(m + 1)/tgamma(n - m + 1));
}

你可能感兴趣的:(算法)