程序设计实践练习3 前置知识
图论部分
1. 图的存储 图的存储 - OI Wiki (oi-wiki.org) ——数据结构
2. dfs 深度优先搜索 DFS(图论) - OI Wiki (oi-wiki.org) ——数据结构
3. bfs 广度有效搜索 BFS(图论) - OI Wiki (oi-wiki.org) ——数据结构
4. 单源最短路,比较重要的是dijkstra 最短路 - OI Wiki (oi-wiki.org) ——离散数学
两个版本,暴力实现复杂度 O ( n 2 ) O(n^2) O(n2),不赘述
堆(优先队列)版本:
struct node
{
int v,w;
};
vector<node> son[1003]; // 存储方式
int dij(int S,int T)
{
priority_queue<pair<int,int> > q; // 优先队列,默认大根堆,即第一关键字大的在前面
for (int i = 1; i <= n; ++i)
dis[i] = 1e8;
dis[S] = 0;
q.push({0, S});
while (!q.empty())
{
int u = q.top().second;
int d = -q.top().first;
q.pop();
if (u == T) return dis[T];
if (d > dis[u]) continue;
for (auto t : son[u]) // son 是 u 点的子节点列表
{
int v = t.v; // 子节点
int w = t.w; // 边权,与具体存储方式有关
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push({-dis[v], v}); // 由于要求最短路,把所有边权置为负数,(最小的就变成最大了)
}
}
}
return dis[T];
}
动态规划
只会考一般的简单线性 d p dp dp,通常是背包问题,或者是极值、计数问题。
基础 动态规划基础 - OI Wiki (oi-wiki.org)
背包参考 背包九讲
记忆化搜索 记忆化搜索 - OI Wiki (oi-wiki.org)
C++ stl
数学
位运算:
-
a ⊗ b = c a \otimes b = c a⊗b=c 等价于 a ⊗ c = b a \otimes c = b a⊗c=b,两者异或等于第三者
-
a < < n = a ∗ 2 n a << n = a * 2 ^ n a<<n=a∗2n, a > > n = ⌊ a 2 n ⌋ a >> n = \lfloor \frac {a}{2 ^n} \rfloor a>>n=⌊2na⌋
-
a + b = 2 ( a & b ) + ( a ⊗ b ) a + b = 2 (a \& b) + (a \otimes b) a+b=2(a&b)+(a⊗b) 不大可能考
组合数
-
杨辉三角打表
f[0][0] = 1, f[i][j] = f[i-1][j] + f[i-1][j-1]
-
组合数公式:
( n m ) = n ! ( n − m ) ! m ! {n \choose m} = \frac {n!}{(n - m)!m!} (mn)=(n−m)!m!n!
一般比较大的组合数,都涉及到逆元计算,不太可能考
const int MOD = 1e9 + 7; //模数
const int lim = 2e6 + 10; // 组合数最大限度
int fc[lim], rfc[lim];
// fc 代表阶乘
// rfc 代表阶乘的逆元
int qp(int x,int p = MOD - 2) // 快速幂
{
int res = 1;
while (p)
{
if (p & 1) res = 1ll * res * x % MOD;
p >>= 1;
x = 1ll * x * x % MOD;
}
return res;
}
void init() // 计算阶乘和阶乘的逆元
{
fc[0] = 1;
for (int i = 1; i < lim; ++i)
fc[i] = 1ll * fc[i - 1] * i % MOD;
rfc[lim - 1] = qp(fc[lim - 1]);
for (int i = lim - 1; i > 0; --i)
rfc[i - 1] = 1ll * rfc[i] * i % MOD;
}
int C(int n,int m) // 组合
{
if (n < 0 || m > n || m < 0) return 0;
return 1ll * fc[n] * rfc[m] % MOD * rfc[n - m] % MOD;
}
int A(int n,int m) // 排列
{
if (m > n || n < 0) return 0;
return 1ll * fc[n] * rfc[n - m] % MOD;
}
最大公约数
int gcd(int a,int b)
{
if (b == 0) return a;
else return gcd(b, a % b);
}
或者直接调用 __gcd(a,b)
,在库 algorithm
中
快速幂
int qp(int x,int p) // 快速幂
{
int res = 1;
while (p)
{
if (p & 1) res = 1ll * res * x % MOD;
p >>= 1;
x = 1ll * x * x % MOD;
}
return res;
}
// 一般都要取模