数论部分知识整理
组合数的若干求法
组合数计算式:
-
预处理阶乘和逆元
\[\binom{n}{m}=fac_m\times inv~fac_n \times inv~fac_{n-m} \]要边乘边模,不然会爆。。
模数不是质数不能用,因为没有逆。
最坏复杂度 \(O(n+log~p)\)
-
杨辉三角
\[\binom {n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1} \]注意边界情况。
C[0][0] = C[1][0]=c[1][1]=1; for (int i = 2; i <= max; ++ i) { c[i][0] = 1; for (int j = 1; j <= i; ++ j) c[i][j] = (C[i-1][j-1]+c[i-1][j]) % p; }
-
\(Lucas\) 定理
\[\binom {n}{m}=\binom{n\bmod p}{m\bmod p}\times \binom{n/p}{m/p}\bmod p \]
int C (int a, int b) {...}
int Lucas (int a, int b, int p) {
if (b > a) return 0;
return C (a % p, b % p) * Lucas (a / p, b / p) % p;
}
luogu P2606 排列计数
题目描述
称一个 \(1 \sim n\) 的排列 \(p_1,p_2, \dots ,p_n\) 是 Magic 的,当且仅当
计算 \(1 \sim n\) 的排列中有多少是 Magic 的,答案可能很大,只能输出模 \(m\) 以后的值
能看出 Magic 序列与二叉树的形式很像。
所以这个题就转化成了能构成多少种满足 \(val_{son} > val_{fa}\) 的树。
因为每个节点的左右儿子相互独立,所以不需要考虑左右儿子之间的关系,满足 dp 的性质,可以树形 dp。
每个节点产生的答案就是 \(C(siz[lson] + siz[rson], siz[lson])\),可以理解为,现在剩余 \(siz[x] -1\) 个数,要分给左右儿子,其中分给左儿子 \(siz[lson]\) 个数字。
哇!我要切蓝题了!交一发,wa了一片……
为什么呢,看数据范围,并不保证模数大于 \(n\)。所以我们需要 Lucas 定理求组合数。
最后这个题就是,树形 dp + Lucas 求组合数。
int Lucas (int a, int b) {
if (!b) return 1;
return 1LL * C (a % m, b % m) * Lucas (a / m, b / m) % m;
}
int getsiz (int x) {
siz[x] = 1;
if (x * 2 <= n) getsiz (x * 2);
if (x * 2 + 1 <= n) getsiz (x * 2 + 1);
siz[x] += siz[x * 2] + siz[x * 2 + 1];
}
int dfs (int x) {
if (x > n) return 1;
return 1LL * Lucas (siz[x] - 1, siz[x * 2]) * dfs (x * 2) % m * dfs (x * 2 + 1) % m;
}
欧拉函数的若干求法
\(\varphi(n)\) 表示小于 \(n\) 的所有数中,与 \(n\) 互质的数的个数。
-
根据定义质因数分解
每次找到一个质因子,在答案里减去 \(n\) 中包含这个质因子的倍数的个数,即 \(n-\frac{n}{i}\),也可以写成 \(\frac{n*(i-1)}{i}\)。
int eul_phi (int n) {
int re = n;
for (int i = 2; i * i <= n; ++ i)
if (n % i == 0) {
re = re / i * (i - 1);
while (n % i == 0) n /= i;
}
if (n > 1) re = re / n * (n - 1);
return re;
}
-
筛法求欧拉函数
线性筛中,通过枚举质数的倍数工作,这恰恰与欧拉函数不谋而合 qwq,所以我们可以通过筛法求。
设 \(p_1\) 为 \(n\) 的最小质因子,\(n'=\frac{n}{p_1}\),所以 \(n\) 是被 \(n'\times p_1\) 筛掉的。
跑筛法的时候要处理两种情况。
-
如果 \(n’ \bmod p_1 = 0\),\(n'\) 包含了 \(n\) 的所有质因子。
\[\varphi(n)=n\times \prod_{i=1}^s\frac{p_i-1}{p_i}\\ =p_1\times n'\times \prod_{i=1}^s\frac{p_i-1}{p_i}\\ =p_1\times \varphi(n') \] -
如果 \(n' \bmod p_1 \neq 0\) ,\(n'\) 与 \(p_1\) 互质,根据欧拉函数的性质
如果 \(gcd (a, b) = 1\),那么 \(\varphi (n) = \varphi(a) \times \varphi (b)\)。
-
void work () {
phi[1] = 1;
for (int i = 2; i <= max; ++ i) {
if (!numlist[i]) {
prime[++ cnt] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= cnt && i * prime[j] <= max; ++ j) {
numlist[i * prime[j]] = 1;
if (i % prime[j])
phi[i * prime[j]] = phi[i] * prime[j];
else {
phi[i * prime[j]] = phi[i] * phi[prime[j]];
break;
}
}
}
}