蓝桥杯知识点总结【预备2020蓝桥杯】

    科技2024-11-20  13

    刷题过程中的一些心得

    慢读题,将讲到的限制条件列出来,对于编程题的话,根据这些限制条件进行猜测数据点,保证简单题的正确率,一次提交就能过!

    从蓝桥杯分值入手,先做简单题,再做难题。 暴力先手,再是优化。 全排列12个数范围里面的都是可以在一秒内搞完的。 对于数据的题,要算的,不要凭空想象。 取点不一定要选择格子,也可以选择格子旁边的线,不要把自己的思路封闭了。

    学会理解题意抽象出我们要的东西,不能被题意背景迷惑了,考的就是思维, 有了思维写下来, 一步一步优化思路, 把一些重复的, 没有多大用的步骤省略掉。

    对于看起来需要排序的题目要注意了,明白他要排序的目的,如果只是计数并且数据范围没有超过索引最大范围的话,那便不用排序,比如说三元组,这个题,看起来需要排序,用sort + 二分, 但是他排序只是为了计数找出有多少个的话,可以用数组计数,前缀和便可以解决问题了, 所以思路要转变, 用某个算法的话,先要明白他要干什么, 能不能找到更方便的办法, 一步一步循序渐进, 当然咯,最主要的就是把题目意思了解清楚了。

    看到最小、最大、最优类字眼,就要往贪心、动态规划方向想了,首先要从暴力入手,再慢慢优化。

    近些年来,比较难的题目都考到了分类讨论,遇到两种变量的时候要定一变一,利用分类讨论的思想去想出简单的办法。

    学会使用excel 。 学会暴力枚举, 保证不重不漏。 递归 从题意抽象出他要考的知识点。

    对于代码填空题目,先要理解他要干什么,在编译器中看看运行效果, 然后进行猜测代码,根据运行出来的结果进行调试,直到调试出正确答案。

    范围判断考点

    n ≤ 30 ⟹ 指 数 级 别 , d f s + 剪 枝 n \leq 30 \Longrightarrow 指数级别, dfs+剪枝 n30,dfs+ n ≤ 100 ⟹ O ( n 3 ) 动 态 规 划 n≤100 \Longrightarrow O(n^3) 动态规划 n100O(n3) n ≤ 1000 ⟹ O ( n 2 ) , O ( n l o g n ) d p , 二 分 n≤1000 \Longrightarrow O(n^2),O(nlogn) dp,二分 n1000O(n2)O(nlogn)dp n ≤ 100000 ⟹ O ( n l o g n ) = > s o r t , 线 段 树 、 树 状 数 组 、 s e t / m a p 、 h e a p 、 二 分 n≤100000 \Longrightarrow O(nlogn) => sort,线段树、树状数组、set/map、heap、二分 n100000O(nlogn)=>sort线set/mapheap n ≤ 1000000 ⟹ O ( n ) h a s h 、 并 查 集 ∣ ∣ 常 数 比 较 小 的 O ( n l o g n ) 的 做 法 : s o r t 、 树 状 数 组 、 h e a p n≤1000000 \Longrightarrow O(n) hash、并查集 || 常数比较小的O(nlogn) 的做法:sort、树状数组、heap n1000000O(n)hashO(nlogn)sortheap n ≤ 10000000 ⟹ O ( n ) 线 性 筛 素 数 n≤10000000 \Longrightarrow O(n) 线性筛素数 n10000000O(n)线 n ≤ 1 0 9 ⟹ O ( n ) 判 断 质 数 n≤10^9 \Longrightarrow O(\sqrt{n}) 判断质数 n109O(n ) n ≤ 1 0 18 ⟹ O ( l o g n ) , 最 大 公 约 数 , 快 速 幂 n≤10^{18} \Longrightarrow O(logn),最大公约数,快速幂 n1018O(logn)

    代码模板

    快速幂

    #include<iostream> using namespace std; int qmi(int a, int b, int p) { int ans = 1; while (b) { if (b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans % p; } int main() { int a, b, p; scanf("%d%d%d", &a, &b, &p); printf("%d\n", qmi(a, b, p)); return 0; }

    并查集

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) const int N = 100010; int n, m, p[N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { scanf("%d%d", &n, &m); _rep(i, 1, n) p[i] = i; while (m--) { char op[3]; int a, b; scanf("%s%d%d", op, &a, &b); if (*op == 'M') p[find(b)] = find(a); // 合并集合 else { // 判断是否在一个集合中 if (find(a) != find(b)) printf("No\n"); else printf("Yes\n"); } } return 0; }

    hash 模板

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef unsigned long long ULL; const int N = 100010, P = 131; char str[N]; ULL h[N], p[N]; ULL get_hash(int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; } int main() { int n, m; scanf("%d%d%s", &n, &m, str); p[0] = 1; for (int i = 0; i < n; ++i) { h[i + 1] = h[i] * P + str[i] - 'a'; p[i + 1] = p[i] * P; } while (m--) { int l1, r1, l2, r2; scanf("%d%d%d%d", &l1, &r1, &l2, &r2); if (get_hash(l1, r1) == get_hash(l2, r2)) puts("Yes"); else puts("No"); } return 0; }

    求最大公约数模板

    #include<iostream> using namespace std; int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } int main() { int a, b; scanf("%d%d", &a, &b); printf("%d\n", gcd(a, b)); return 0; }

    求最大公倍数模板

    #include<iostream> using namespace std; int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } int lcm(int a, int b) { return a * b / gcd(a, b); } int main() { int a, b; scanf("%d%d", &a, &b); printf("%d\n", lcm(a, b)); return 0; }

    线性筛法求质数模板

    #include<iostream> #include<cstdio> using namespace std; #define _for(i, a, b) for (int i = (a); i < (b); ++i) const int N = 1000010; int primes[N], cnt; bool st[N]; inline void get_primes(int n) { for (int i = 2; i <= n; ++i) { if (!st[i]) primes[cnt++] = i; for (int j = 0; i * primes[j] <= n; ++j) { st[i * primes[j]] = true; if (i % primes[j] == 0) break; } } } int main() { int n; scanf("%d", &n); get_primes(n); _for(i, 0, cnt) printf("%d ", primes[i]); printf("\n"); return 0; }

    高精度模板

    #include<iostream> #include<cstring> #include<vector> #include<algorithm> using namespace std; #define FOR(i, a) for (int i = (a); ~i; --i) typedef vector<int> VI; VI add(VI & a, VI & b) { VI c; for (int i = 0, t = 0; i < a.size() || i < b.size() || t; ++i) { if (i < a.size()) t += a[i]; if (i < b.size()) t += b[i]; c.push_back(t % 10); t /= 10; } return c; } bool cmp(VI& a, VI& b) { if (a.size() != b.size()) return a.size() > b.size(); FOR(i, a.size() - 1) if (a[i] != b[i]) return a[i] > b[i]; return true; } VI sub(VI a, VI b) { VI c; int t = 0; FOR(i, a.size() - 1) { t += a[i]; if (i < b.size()) t -= b[i]; c.push_back((t + 10) % 10); if (t < 0) t = -1; else t = 0; } reverse(c.begin(), c.end()); while (c.size() > 1 && !c.back()) c.pop_back(); return c; } VI mul(VI& a, int b) { VI c; for (int i = 0, t = 0; i < a.size() || t; ++i) { if (i < a.size()) t += a[i] * b; c.push_back(t % 10); t /= 10; } return c; } VI div(VI& a, int& b, int& r) { VI c; FOR(i, a.size() - 1) { r = r * 10 + a[i]; c.push_back(r / b); r %= b; } reverse(c.begin(), c.end()); while (c.size() > 1 && !c.back()) c.pop_back(); return c; } void input(VI& c) { FOR(i, c.size() - 1) cout << c[i]; cout << endl; } int main() { VI a, b, c; string s, ss; int d, r = 0; cin >> s >> ss >> d; FOR(i, s.size() - 1) a.push_back(s[i] - '0'); FOR(i, ss.size() - 1) b.push_back(ss[i] - '0'); c = add(a, b); cout << "a + b = "; input(c); if (cmp(a, b)) { cout << "a - b = "; c = sub(a, b); } else { cout << "a - b = -"; c = sub(b, a); } input(c); c = mul(a, d); cout << "a * d = "; input(c); c = div(a, d, r); cout << "a / d = "; input(c); cout << "余数为:" << r << endl; return 0; }

    树状数组模板

    模板题目

    #include<iostream> #include<cstdio> using namespace std; #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) typedef long long LL; const int N = 500010; LL c[N], n, m; void add(int x, LL k) { for (; x <= n; x += x & -x) c[x] += k; } LL ask(int x) { LL ans = 0; for (; x; x -= x & -x) ans += c[x]; return ans; } int main() { scanf("%lld%lld", &n, &m); _rep(i, 1, n) { LL x; scanf("%lld", &x); add(i, x); } while (m--) { LL x, y; int op; scanf("%d%lld%lld", &op, &x, &y); if (op == 1) add(x, y); else printf("%lld\n", ask(y) - ask(x - 1)); } return 0; }

    线段树模板

    模板题目

    #include<iostream> #include<cstdio> using namespace std; #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) typedef long long LL; const int N = 100010; int n, m; LL w[N]; struct Node { int l, r; LL v, lz; }tr[N << 2]; inline void push_up(int u) { tr[u].v = tr[u << 1].v + tr[u << 1 | 1].v; } inline void eval(Node& t, LL k) { t.v += ((LL)t.r - t.l + 1) * k; t.lz += k; } inline void push_down(int u) { LL& lz = tr[u].lz; eval(tr[u << 1], lz); eval(tr[u << 1 | 1], lz); lz = 0; } void build(int u, int l, int r) { tr[u] = { l, r, 0, 0 }; if (l == r) tr[u].v = w[l]; else { int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); push_up(u); } } void modify(int u, int l, int r, LL k) { Node& t = tr[u]; if (t.l >= l && t.r <= r) eval(t, k); else { push_down(u); int mid = t.l +t.r >> 1; if (l <= mid) modify(u << 1, l, r, k); if (r > mid) modify(u << 1 | 1, l, r, k); push_up(u); } } LL query(int u, int l, int r) { Node& t = tr[u]; if (t.l >= l && t.r <= r) return t.v; else { push_down(u); LL ans = 0; int mid = t.l + t.r >> 1; if (l <= mid) ans += query(u << 1, l, r); if (r > mid) ans += query(u << 1 | 1,l, r); return ans; } } int main() { scanf("%d%d", &n, &m); _rep(i, 1, n) scanf("%lld", &w[i]); build(1, 1, n); while (m--) { int op, x, y; LL k; scanf("%d%d%d", &op, &x, &y); if (op == 1) { scanf("%lld", &k); modify(1, x, y, k); } else printf("%lld\n", query(1, x, y)); } return 0; }
    Processed: 0.020, SQL: 8