本文最后更新于 2024-08-29T19:04:32+08:00
普及- P3383 【模板】线性筛素数 给定一个范围 $n$,有 $q$ 个询问,每次输出第 $k$ 小的素数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <bits/stdc++.h> using namespace std;const int N = 1e8 + 7 ;int n, q;bool prime[N];int ans[N], tot;int main () { scanf ("%d%d" , &n, &q); for (int i = 2 ; i <= n; ++i) { if (!prime[i]) { ans[++tot] = i; } for (int j = 1 ; j <= tot && i * ans[j] <= n; ++j) { prime[i * ans[j]] = 1 ; if (!(i % ans[j])) { break ; } } } for (int i = 1 ; i <= q; ++i) { int x; scanf ("%d" , &x); printf ("%d\n" , ans[x]); } return 0 ; }
P3378 【模板】堆 给定一个数列,初始为空,支持下面三种操作:
给定一个整数 $x$,请将 $x$ 加入到数列中。
输出数列中最小的数。
删除数列中最小的数(如果有多个数最小,只删除 $1$ 个)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> using namespace std;int n; priority_queue<int , vector<int >, greater<int >> heap;int main () { scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) { int x; scanf ("%d" , &x); if (x == 1 ) { int y; scanf ("%d" , &y); heap.push (y); } else if (x == 2 ) { printf ("%d\n" , heap.top ()); } else if (x == 3 ) { heap.pop (); } } return 0 ; }
P3370 【模板】字符串哈希 给定 $N$ 个字符串(第 $i$ 个字符串长度为 $M_i$,字符串内包含数字、大小写字母,大小写敏感),请求出 $N$ 个字符串中共有多少个不同的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> using namespace std;const int base = 47 ;int n, st[10001 ], cnt;int hash_ (string s) { int ans = 0 ; for (int i = 0 ; i < s.length (); ++i) { ans = ans * base + s[i]; } return ans; }int main () { scanf ("%d" , &n); for (int i = 1 ; i <= n; ++i) { string s; cin >> s; st[i - 1 ] = hash_ (s); } sort (st, st + n); unique (st, st + n); for (int i = 1 ; i <= n; i++) { if (st[i - 1 ] < st[i]) { ++cnt; } else { break ; } } printf ("%d" , cnt + 1 ); return 0 ; }
P1226 【模板】快速幂 给定三个整数 $a,b,p$,求 $a^b \bmod p$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <bits/stdc++.h> using namespace std;long long a, b, mod;long long qpow (int x, int y) { if (!y) { return 1 ; } long long n = qpow (x, y / 2 ) % mod; long long m = n * n % mod; if (y % 2 ) { m *= x; } return m % mod; }int main () { scanf ("%lld%lld%lld" , &a, &b, &mod); cout << a << "^" << b << " mod " << mod << "=" << qpow (a, b); return 0 ; }
P1177 【模板】排序(归并排序做法) 将读入的 $n$ 个数从小到大排序后输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <bits/stdc++.h> using namespace std;const int N = 1e5 + 5 ;int n;int a[N], b[N];int ans;void mergesort (int l, int r) { if (l >= r) { return ; } int mid = (l + r) >> 1 ; mergesort (l, mid); mergesort (mid + 1 , r); int i = l, j = mid + 1 , k = l; while (i <= mid && j <= r) { if (a[i] <= a[j]) { b[k++] = a[i++]; } else { b[k++] = a[j++]; } } while (i <= mid) { b[k++] = a[i++]; } while (j <= r) { b[k++] = a[j++]; } for (int i = l; i <= r; i++) { a[i] = b[i]; } return ; }int main () { scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) { scanf ("%d" , &a[i]); } mergesort (1 , n); for (int i = 1 ; i <= n; i++) { printf ("%d " , a[i]); } return 0 ; }
B3647 【模板】Floyd 给出一张由 $n$ 个点 $m$ 条边组成的无向图。求出所有点对 $(i,j)$ 之间的最短路径。数据中可能存在重边。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <bits/stdc++.h> using namespace std;const int N = 105 ;const int inf = 2147483647 ;int n, m;int dis[N][N];int main () { scanf ("%d%d" , &n, &m); for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= n; +j+) { dis[i][j] = inf; } } for (int i = 1 ; i <= n; ++i) { dis[i][i] = 0 ; } for (int i = 1 ; i <= m; ++i) { int x, y, z; scanf ("%d%d%d" , &x, &y, &z); if (dis[x][y] != inf && dis[y][x] != inf) { dis[x][y] = min (dis[x][y], z), dis[y][x] = min (dis[x][y], z); } else if (x != y) { dis[x][y] = z, dis[y][x] = z; } else if (x == y) { dis[x][y] = 0 ; } } for (int k = 1 ; k <= n; ++k) { for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= n; ++j) { dis[i][j] = min (dis[i][j], dis[i][k] + dis[k][j]); } } } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= n; ++j) { if (dis[i][j] == inf) { printf ("0 " ); } else { printf ("%d " , dis[i][j]); } } printf ("\n" ); } return 0 ; }
B3644 【模板】拓扑排序 / 家谱树 有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。给出每个人的后代的信息。输出一个序列,使得每个人的后辈都比那个人后列出。 第 $1$ 行一个整数 $N$($1 \le N \le 100$),表示家族的人数。接下来 $N$ 行,第 $i$ 行描述第 $i$ 个人的后代编号 $a_{i,j}$,表示 $a_{i,j}$ 是 $i$ 的后代。每行最后是 $0$ 表示描述完毕。 输出一个序列,使得每个人的后辈都比那个人后列出。如果有多种不同的序列,输出任意一种即可。
样例输入1
1 2 3 4 5 6 5 0 4 5 1 0 1 0 5 3 0 3 0
样例输出1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <bits/stdc++.h> using namespace std;const int N = 1e3 + 5 ;int n;int ltt, head[N];int rd[N]; queue<int > tp;struct G { int from, to; } edge[N * N];void addedge (int u, int v) { edge[++ltt] = (G) { v, head[u] }; head[u] = ltt; }void topo () { queue<int > q; for (int i = 1 ; i <= n; ++i) { if (!rd[i]) { q.push (i); } } while (!q.empty ()) { int u = q.front (); q.pop (); tp.push (u); for (int i = head[u]; i; i = edge[i].to) { int v = edge[i].from; if (!(--rd[v])) { q.push (v); } } } return ; }int main () { scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) { int x; while (1 ) { scanf ("%d" , &x); if (x != 0 ) { addedge (i, x); } else { break ; } rd[x]++; } } topo (); while (!tp.empty ()) { printf ("%d " , tp.front ()); tp.pop (); } return 0 ; }
B3614 【模板】栈 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <bits/stdc++.h> #define int unsigned long long using namespace std;int T;int n;signed main () { cin >> T; for (int i = 1 ; i <= T; ++i) { stack<int > stk; cin >> n; for (int j = 1 ; j <= n; ++j) { string op; cin >> op; if (op == "push" ) { int x; cin >> x; stk.push (x); } else if (op == "pop" ) { if (!stk.empty ()) { stk.pop (); } else { printf ("Empty\n" ); } } else if (op == "query" ) { if (!stk.empty ()) { cout << stk.top () << "\n" ; } else { printf ("Anguei!\n" ); } } else { cout << stk.size () << "\n" ; } } } return 0 ; }
B3616 【模板】队列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <bits/stdc++.h> #define int unsigned long long using namespace std;int n;signed main () { queue<int > que; cin >> n; for (int j = 1 ; j <= n; ++j) { int op; cin >> op; if (op == 1 ) { int x; cin >> x; que.push (x); } else if (op == 2 ) { if (!que.empty ()) { que.pop (); } else { printf ("ERR_CANNOT_POP\n" ); } } else if (op == 3 ) { if (!que.empty ()) { cout << que.front () << "\n" ; } else { printf ("ERR_CANNOT_QUERY\n" ); } } else { cout << que.size () << "\n" ; } } return 0 ; }
B3656 【模板】双端队列 要求实现 $m$ 个双端队列,支持如下的 $q$ 次操作:
push_back(a,x):在第 $a$ 个双端队列中从尾部插入一个元素 $x$;
pop_back(a):在第 $a$ 个双端队列中从尾部弹出一个元素。
push_front(a,x):在第 $a$ 个双端队列中从头部插入一个元素 $x$;
pop_front(a):在第 $a$ 个双端队列中从头部弹出一个元素。
size(a):查询第 $a$ 个双端队列的元素个数;
front(a):查询第 $a$ 个双端队列的队首元素;
back(a):查询第 $a$ 个双端队列的队尾元素; 对于 pop_back,pop_front,front 和 back 操作,若当前双端队列为空则不进行,直接跳过该次操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <bits/stdc++.h> using namespace std;const int N = 1e6 + 7 ;int q; list<int > a[N];int main () { scanf ("%d" , &q); string k; for (int i = 1 ; i <= q; ++i) { cin >> k; if (k == "pop_back" ) { int m; cin >> m; if (!a[m].empty ()) { a[m].pop_back (); } } else if (k == "push_back" ) { int m, n; scanf ("%d%d" , &m, &n); a[m].push_back (n); } else if (k == "pop_front" ) { int m; scanf ("%d" , &m); if (!a[m].empty ()) { a[m].pop_front (); } } else if (k == "push_front" ) { int m, n; cin >> m >> n; a[m].push_front (n); } else if (k == "size" ) { int m; cin >> m; printf ("%d\n" , a[m].size ()); } else if (k == "front" ) { int m; cin >> m; if (!a[m].empty ()) { printf ("%d\n" , a[m].front ()); } } else if (k == "back" ) { int m; cin >> m; if (!a[m].empty ()) { printf ("%d\n" , a[m].back ()); } } } return 0 ; }
P10815 【模板】快速读入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <bits/stdc++.h> using namespace std;const int N = 1e8 + 5 ;int n;int a[N];int ans;inline int read () { int x = 0 , f = 1 ; char ch = getchar_unlocked (); while (!isdigit (ch)) { if (ch == '-' ) f = -1 ; ch = getchar_unlocked (); } while (isdigit (ch)) { x = (x << 1 ) + (x << 3 ) + (ch ^ 48 ); ch = getchar_unlocked (); } return x * f; }inline void write (int x) { if (x < 0 ) { putchar ('-' ); x = -x; } if (x > 9 ) { write (x / 10 ); } putchar (x % 10 + '0' ); }int main () { n = read (); for (int i = 1 ; i <= n; ++i) { a[i] = read (); ans += a[i]; } write (ans); return 0 ; }
B3694 数列离散化 给定一个长度为 $n$ 的数列 $a$。定义 $\mathrm{rank}(i)$ 表示数列 $a$ 中比 $a_i$ 小的不同数字个数再加一。 对 $1 \leq i \leq n$,现在请你求出所有的 $\mathrm{rank}(i)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <bits/stdc++.h> using namespace std;const int N = 1e5 + 7 ;int T;int n;int a[N], rk[N];int main () { scanf ("%d" , &T); for (int i = 1 ; i <= T; ++i) { scanf ("%d" , &n); for (int i = 1 ; i <= n; ++i) { scanf ("%d" , &a[i]); } for (int i = 1 ; i <= n; ++i) { rk[i] = a[i]; } sort (rk + 1 , rk + 1 + n); int len = unique (rk + 1 , rk + 1 + n) - rk - 1 ; for (int i = 1 ; i <= n; ++i) { a[i] = lower_bound (rk + 1 , rk + 1 + len, a[i]) - rk; } for (int i = 1 ; i <= n; ++i) { printf ("%d " , a[i]); } printf ("\n" ); } return 0 ; }
B2105 矩阵乘法 计算两个矩阵的乘法。$n \times m$ 阶的矩阵 $A$ 乘以 $m \times k$ 阶的矩阵 $B$ 得到的矩阵 $C$ 是 $n \times k$ 阶的,且 $C[i][j]=A[i][0] \times B[0][j]+A[i][1] \times B[1][j]+$ …… $+A[i][m-1] \times B[m-1][j](C[i][j]$ 表示 $C$ 矩阵中第 $i$ 行第 $j$ 列元素)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <bits/stdc++.h> using namespace std;const int N = 105 ;int n, m, p;int a[N][N], b[N][N], c[N][N];int main () { scanf ("%d%d%d" , &n, &m, &p); for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= m; ++j) { scanf ("%d" , &a[i][j]); } } for (int i = 1 ; i <= m; ++i) { for (int j = 1 ; j <= p; ++j) { scanf ("%d" , &b[i][j]); } } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= p; ++j) { for (int k = 1 ; k <= m; ++k) { c[i][j] += a[i][k] * b[k][j]; } } } for (int i = 1 ; i <= n; ++i) { for (int j = 1 ; j <= p; ++j) { printf ("%d " , c[i][j]); } printf ("\n" ); } return 0 ; }