noip 数学整理

// 质数判定
(1) 暴力
bool check(int x) {
    for (int i = 2; i * i <= x; ++i) if (x % i == 0) return 0;
    return 1;
}
(2)miller_rabin
bool check(LL a) {
	for (int i = 0; i < 12; ++i) {
		if(f[i] >= a) break;
		if(Qpow(f[i], a - 1, a) != 1) return 0;
		LL pp = a - 1;
		while(pp % 2 == 0) {
			pp /= 2; LL y = Qpow(f[i], pp, a);
			if(Qmul(y, y, a) == 1 && y != 1 && y != a - 1) return 0;
		}
	} return 1;
}

//n的所有约数
vector <int> a;
for (int i = 2; i * i <= n; ++i) {
    if (n % i == 0) {
        a.push_back(i);
        if (i * i != n) a.push_back(n / i);
    }
}

//分解质因数
vector <int> p, c;
for (int i = 2; i * i <= n; ++i) {
    if (n % i == 0) {
        p.push_back(i);
        int cnt = 0;
        while (n % i == 0) ++ cnt, n /= i;
        c.push_back(cnt);
    }
}
if (n > 1) p.push_back(n), c.push_back(1);

//线性筛
(1)筛质数
for (int i = 2; i <= lim; ++i) {
    if (!vis[i]) pri[++ cnt] = i;
    for (int j = 1; j <= cnt && i * pri[j] <= lim; ++j) {
        vis[i * pri[j]] = 1;
        if (i % pri[j] == 0) break;
    }
}

(2)筛欧拉函数
phi[1] = 1;
for (int i = 2; i <= lim; ++i) {
    if (!vis[i]) pri[++ cnt] = i, phi[i] = i - 1;
    for (int j = 1; j <= cnt && i * pri[j] <= lim; ++j) {
        vis[i * pri[j]] = 1;
        if (i % pri[j] == 0) {
            phi[i * pri[j]] = phi[i] * pri[j]; break;
        }
        phi[i * pri[j]] = phi[i] * phi[pri[j]];
    }
}

(3) 筛约束约数个数
记t[i]为i的约数个数,e[i]为i的最小素因子的个数
因为是线性筛,每个数只被它最小的质因子筛到,所以
a pri[j]是i*pri[j]的最小质因子
b 如果i是pri[j]的倍数,pri[j]也是i的最小质因子
<1> i是素数,t[i] = 2, e[i] = 1
<2> i是pri[j]的倍数
    t[i * pri[j]] = t[i] / (e[i] + 1) * (e[i] + 2)
    e[i] = e[i] + 1
<3> i不是pri[j]的倍数
    t[i * pri[j]] = t[i] * t[pri[j]]
    e[i * pri[j]] = 1

for (int i = 2; i <= lim; ++i) {
    if (!vis[i]) pri[++ cnt] = i, t[i] = 2, e[i] = 1;
    for (int j = 1; j <= cnt && i * pri[j] <= lim; ++j) {
        vis[i * pri[j]] = 1;
        if (i % pri[j] == 0) {
            e[i * pri[j]] = e[i] + 1;
            t[i * pri[j]] = t[i] / (e[i] + 1) * (e[i] + 2); break;
        }
        e[i * pri[j]] = 1;
        t[i * pri[j]] = t[i] * t[pri[j]];
    }
}

(4)筛约数和
记t[i]为i的约数和,e[i]为i的最小素因子的那一项等比数列
t[i] = (1 + p1 + p1^2 + ...)(1 + p2 + p2^2 + ....) ...(1 + pn + pn^2 + ...)
e[i] = (1 + p1 + p1^2 + ...)
因为是线性筛,每个数只被它最小的质因子筛到,所以
a pri[j]是i*pri[j]的最小质因子
b 如果i是pri[j]的倍数,pri[j]也是i的最小质因子
<1> i是素数,t[i] = i + 1, e[i] = i + 1
<2> i是pri[j]的倍数 
    t[i * pri[j]] = t[i] / e[i] * (e[i] * pri[j] + 1)
    e[i * pri[j]] = e[i] * pri[j] + 1
<3> i不是pri[j]的倍数
    t[i * pri[j]] = t[i] * (pri[j] + 1)
    e[i * pri[j]] = pri[j] + 1

for (int i = 2; i <= lim; ++i) {
    if(!vis[i]) pri[++ cnt] = i, e[i] = t[i] = i + 1;
    for (int j = 1; j <= cnt && i * pri[j] <= lim; ++j) {
        vis[i * pri[j]] = 1;
        if (i % pri[j] == 0) {
            t[i * pri[j]] = t[i] / e[i] * (e[i] * pri[j] + 1);
            e[i * pri[j]] = e[i] * pri[j] + 1;
        } 
        t[i * pri[j]] = t[i] * (pri[j] + 1);
        e[i * pri[j]] = pri[j] + 1;
    }
}

//ECGCD
void Exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {x = 1; y = 0; return;}
    Exgcd(b, a % b, y, x);
    y -= a / b * x;
}
方程 ax + by = c有解, 当且仅当 gcd(a, b) | c
d = gcd(a, b)
a /= d, b /= d, c /= d
通解: x = x * c + k * b, y = y * c - k * a 
最小正整数解 x *= c, x = (x % b + b) % b

//线性同余方程
求解 ax=b(mod m)
转化为:ax + my = b

tips:求解 ax + by = c时
若 a < 0, 则 a = -a, c = -c

//线性同余方程组
x = b1 (mod a1)
x = b2 (mod a2)

b1 + a1 * x1 = b2 + a2 * x2
a1 * x1 + a2 * x2 = b2 - b1
解出最小的正整数解x'
得到新方程 x = (a1 * x' +b1) (mod lcm(a1, b2))

LL excrt() {
	LL M = a[1], B = b[1], x, y;
	for (int i = 2; i <= n; ++i) {
		LL C = b[i] - B;
		LL d = gcd(M, a[i]);
		if (C % d) return -1;
		exgcd(M, a[i], x, y);
		x = Mul(x, C / d, a[i] / d);
		B += x * M;
		M = M / d * a[i];
		B = (B % M + M) % M;
	}
	return B;
}

//欧拉函数
phi[i]表示1...i中与i互质数的个数
i = p1 ^ a1 * p2 ^ a2 *...pn ^ a
phi[i] = sum{i / pj * (pj - 1)}

//欧拉定理
当gcd(a, n) = 1时, a ^ phi[n] = 1 (mod n)
推论
<1> 若gcd(a, n) = 1, 则a ^ b = a ^ (b % phi[n]) (mod n)
<2> 若b > phi[n], 则a ^ b = a ^ (b % phi[n] + phi[n]) (mod n)

//费马小定理
<1> p是质数,gcd(a, p) = 1, 则a ^ (p - 1) = 1 (mod p)
<2> p是质数,对于任意a, a ^ p = a (mod p)

//乘法逆元
a * x = 1 (mod m)
x 为 a 在mod m意义下的逆元
求法 
<1> m 为质数 pow(a, m - 2) 为逆元
<2> ax + bm = 1, exgcd求解即可
<3> 递推 inv[1] = 1, inv[i] = (p - p / i) * inv[p % i]

//组合数 C(n, m) = n! / (m! * (n - m)!)
递推 :
c[0][0] = 1;
for (int i = 1; i <= n; ++i) {
	c[i][0] = c[i][i] = 1;
	for (int j = 1; j <= i - 1; ++j) 
	c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}

//二项式定理
(a + b) ^ n = sum {C(n, i) * a ^ i * b ^ (n - i)} (0 <= i <= n)

//卡特兰数
P(n) = C(2n, n) - C(2n, n - 1) = 1 / (n + 1) * C(2n, n)
前几项:(n从0开始)
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786
递推:
P0 = 1
<1> Pn = sum {Pi * Pn - i + 1} (0 <= i <= n - 1)
<2> Pn+1 = 2 * (2n + 1) / (n + 2) * Pn
奇卡特兰数满足 n = 2 ^ k - 1
https://quincyqiang.cn/2017/08/24/06-%E5%8D%A1%E7%89%B9%E5%85%B0%E6%95%B0/
http://blog.miskcoo.com/2015/07/catalan-number

  

猜你喜欢

转载自www.cnblogs.com/oi-forever/p/9905718.html