CSP-J/S复赛集训(1):必背模板Ⅰ

一、二分模板

1. 求最小值模板

牢记位运算和正常运算的转换:
x > > y = ⌊ x 2 y ⌋ x < < y = 2 y x x>>y=\lfloor \frac{x}{2y} \rfloor \\ x<<y=2yx x>>y=2yxx<<y=2yx

表达式
x >> y ⌊ x 2 y ⌋ \lfloor \frac{x}{2y} \rfloor 2yx
x << y 2 y x 2yx 2yx
x & 1 b ≡ 求这个值 ( m o d 2 ) b \equiv 求这个值 \pmod 2 b求这个值(mod2)
while (l < r) {
    int mid = l + (r - l >> 1); // int mid = (l + r) / 2;
    if (check(mid))
        r = mid;
    else
        l = mid + 1;
}

2. 求最大值模板

while (l < r) {
    int mid = l + (r - l - 1 >> 1); // int mid = (l + r + 1) / 2
    if (check(mid))
        l = mid;
    else
        r = mid - 1;
}

二、数学

1. 运算

① 快速幂模板

原理:对于要求的 a b a^b ab
a b = { 2 a b 2 if  b ≡ 1 ( m o d 2 ) a × 2 a ⌊ b 2 ⌋ if  b ≡ 0 ( m o d 2 ) a^b = \begin{cases} 2a^{\frac{b}{2}} & \text{if } b \equiv 1 \pmod 2 \\ a\times2a^{\lfloor \frac{b}{2} \rfloor} & \text{if } b \equiv 0 \pmod 2 \end{cases} ab={2a2ba×2a2bif b1(mod2)if b0(mod2)

int qpow(int a, int b) {
    int ret = 1;
    while (b) {
        if (b & 1) // if (b % 2 == 1)
            ret = (ret * a) % MOD;
        a = (a * a) % MOD;
        b >>= 1; // b /= 2
    }
    return ret;
}

② 最大公约数/最小公倍数

int gcd(int x, int y) {
    return y ? gcd(y, x % y) : x;
}
int lcm(int x, int y) {
    return x / gcd(x, y) * y; // 避免爆long long
}

③ 扩展欧几里得算法

概念:exgcd() 返回 gcd() 的返回结果,其中还可以求得两数 x , y x,y x,y 满足下面的条件:
a x + b y = g c d ( a , b ) ( x , y ∈ Z ) ax+by=gcd(a,b)(x,y\in \mathbb Z ) ax+by=gcd(a,b)(x,yZ)

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

2. 素数

① 欧拉筛法

memset(isPrime, 1, sizeof(isPrime));
for (int i = 2; i <= n; i++) {
    if (isPrime[i]) prime[pos++] = i; // 存入素数表
    for (int j = 1; j <= pos-1 && i * prime[j] <= n; j++) { // 筛掉i所有素数倍的数,直到i的最小素因子倍位置
        isPrime[i * prime[j]] = 0; // 标记为合数
        if (i % isPrime[j] == 0) break; // 筛到最小素因子为止
    }
}

② 判断素数

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

③ 分解质因数

最常用写法:

for (int i = 2; i * i <= n; i++)
    while (n % i == 0) {
        printf("%d ", i);
        n /= i;
    }
if (n > 2) printf("%d", n);

大数据规模写法:

while (n % 2 == 0) rintf("2 ")
for (int i = 3; i * i <= n; i += 2)
    while (n % i == 0) {
        printf("%d ", i);
        n /= i;
    }
if (n > 2) printf("%d", n);

三、图论基础

1. 组合数

dp[1][1] = 1;
dp[2][1] = dp[2][2] = 1;
for (int i = 3; i <= n; i++)
    for (int j = 1; j <= i; j++)
        dp[i][j] = dp[i-1][j] + dp[i-1][j-1];

2. Floyd-Warshall 算法(多源最短路)

for (int k = 1; k <= n; k++) // 中转站
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            if (dis[i][j] == INF || i == j) continue; // 可以降一点时间
            dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j];
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值