标签:组合数 memset size div 预处理 组成 lan power 筛选
数论+数学从入门到放弃
(因为博主数论非常不好,如果写错了请及时提醒博主)
数论里面非常常用的东西
(注意模数为质数)
首先预处理阶乘
jc[0] = 1;
for(int i = 1; i <= n; i ++)
jc[i] = (jc[i - 1] * i) % mod;
然后预处理阶乘逆元
(power为带模的快速幂)
inv[n] = power(jc[n], mod - 2);
for(int i = n - 1; i >= 0; i --)
inv[i] = (inv[i + 1] * (i + 1)) % mod;
一般用来计算模数较小但数据范围很大的组合数
$\dbinom{n}{m} \equiv \dbinom{n\bmod p}{m\bmod p} \times \dbinom{n \div p}{m \div p} \pmod{p}$
若出现n < m的情况,则答案为0
多重集是指包含重复元素的广义集合
设值为$a_i$的数有$n_i$个,$n = \sum n_i$ ,那么该集合的全排列个数为
$\dfrac{n!}{\prod n_i!}$
$Cat_n = \dfrac{C^n_{2n}}{n + 1} = C^n_{2n} - C^{n - 1}_{2n}$
以下问题与Catalan数列相关
使用试除法,用小于等于sqrt(x)的数试除 x 若能除尽,则 x 为合数
bool prime(int x) {
if(x == 2)return 1;
if(x % 2 == 0 || x == 1)return 0;
for(int i = (int)sqrt(x) | 1; i >= 3; i -= 2)
if(x % i == 0)return 0;
return 1;
}
//复杂度很低的筛法
for(int i = 2; i <= n; i ++)
if(! w[i]) {
p[ ++cnt] = i;
for(int j = 2; j <= i; j ++)w[i * j] = 1;
}
for(int i = 2; i <= n; i ++) {
if(! w[i])p[ ++cnt] = i;
for(int j = 1; j <= cnt && i * p[j] <= n; j ++) {
w[i * p[j]] = 1;
if(i % p[j] == 0)break;
}
}
(一般情况不需要使用)
从小到大累积质因子
//线性筛法
int v[MAXN], prime[MAXN];
void primes(int n) {
memset(v, 0, sizeof(v));//最小质因子
m = 0;//质数数量
for(int i = 2; i <= n; i ++) {
if(v[i] == 0)
v[i] = i, prime[++ m] = i;
//给当前的数i乘上一个质因子
for(int j = 1; j <= m; j ++) {
//i有比prime[j]更小的质因子就停止循环
if(prime[j] > v[i] || prime[j] > n / i)break;
//prime[j]是合数i*prime[j]的最小质因子
v[i * prime[j]] = prime[j];
}
}
求不定方程ax + by = gcd(a,b)的一组特解
void exgcd(int a, int b, int &d, int &x, int &y) {
b ? exgcd(b, a % b, d, y, x), y -= x * (a / b) : d = a, x = 1, y = 0;
}
若整数B满足$B \equiv \dfrac{1}{A} \pmod{P}$ ,则称B为A在模P意义下的乘法逆元
标签:组合数 memset size div 预处理 组成 lan power 筛选
原文地址:https://www.cnblogs.com/akakw1/p/9923857.html