整理的算法模板合集: ACM模板


目录

  • A、杰杰国王的平等节(easy)【签到】
  • B、最佳复习效果(easy - mid)【二分查找】
  • C、无限之路(mid - hard)【离散化+前缀和】
  • D、Is acm here?(easy)【签到】
  • E、填数游戏(easy)【规律】
  • F、阿伟的店铺(easy - mid)【中位数】
  • G、魔法阵(mid - hard)【线性DP】
  • H、公益活动(mid)【简单DFS】
  • I、选拔人才(mid - hard)【贪心+优先队列 / 暴力贪心】
  • J、2048(mid - hard)【大模拟】
  • K、Alice和Bob的爱恨情仇(mid - hard)【构造】
  • L、石同学的树(hard)【树hash】
  • M、简单数论(hard)【欧拉函数+快速幂+拓展欧几里得+因数分解+解同余方程(doge)】

比赛地址:https://ac.nowcoder.com/acm/contest/9681#question
邀请码:swpu2020

大家可以点开上面的比赛地址进入比赛页面提交代码补题。

A、杰杰国王的平等节(easy)【签到】

签到题,只需要找到序列最大值计算即可。

#include <iostream>
using namespace std;
int a[1000005];
int main() {int n, m = 0, sum = 0;scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);m = max(m, a[i]);}for (int i = 1; i <= n; i++) {sum += m - a[i];}printf("%d", sum);return 0;
}

B、最佳复习效果(easy - mid)【二分查找】

数据为10510^5105,O(n2)O(n^2)O(n2)乱搞是过不去的(其实数据还是有点弱)
我们可以使用二分查找 O(nlogn)O(nlogn)O(nlogn) 稳定通过本题。

#include <stdio.h>
#define max(x,y) (x>y?x:y)
const int maxn = 1e5 + 5;
int n, k, a[maxn], ans;
void find(int l, int r, int val, int &pos) {if (l >= r)return;int m = (l + r) / 2;if (a[m] <= val)find(m + 1, r, val, pos);else {pos = m;find(l, m, val, pos);}
}
int main() {scanf("%d%d", &n, &k);for (int i = 0; i < n; i++)scanf("%d", &a[i]);for (int i = 0; i < n; i++) {int x = a[i], lim = k - a[i], pos = -1;find(0, i, lim, pos);if (pos == -1)pos = i;if (pos - 1 < 0)continue;int y = a[pos - 1];ans = max(ans, x * y);}printf("%d", ans);return 0;
}

开一个桶暴力搞(数据较弱)

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int a[10005];
int main() {int n, k;scanf("%d %d", &n, &k);int Max = 0;for (int i = 1; i <= n; i++) {int digit;scanf("%d", &digit);a[digit]++;}for (int i = 1; i <= 10000; i++)for (int j = 1; j <= 10000; j++) {if (i == j) {if (a[i] >= 2) {if (i + j <= k)Max = max(Max, i * j);}} else {if (a[i] >= 1 && a[j] >= 1) {if (i + j <= k)Max = max(Max, i * j);}}}printf("%d", Max);return 0;
}

C、无限之路(mid - hard)【离散化+前缀和】

离散化+前缀和模板题

我们发现数轴的数据达到了101810^{18}1018,查询的数据达到了10510^5105,所以我们查询的时候需要用前缀和O(1)O(1)O(1)查询,由于数轴过长,我们不可能开一个101810^{18}1018的数组存下整个数轴,所以我们需要用到一个离散化的思想(具体百度)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
typedef long long ll;
const int N = 500007;
using namespace std;ll n, m;
ll a[N];
vector<ll>b;
ll sum[N];
ll X[N], C[N], L[N], R[N];
ll tot = 0;
ll Find(ll x)
{ll res = lower_bound(b.begin(), b.end(), x) - b.begin();return res;
}int main()
{//freopen("1.in", "r", stdin);//freopen("1.out", "w", stdout);scanf("%d%d", &n, &m);b.push_back(-1e18);for(int i = 1; i <= n; ++ i){scanf("%lld%lld", &X[i], &C[i]);b.push_back(X[i]);}for(int i = 1; i <= m; ++ i){scanf("%lld%lld", &L[i], &R[i]);b.push_back(L[i]);b.push_back(R[i]);}sort(b.begin(), b.end());b.erase(unique(b.begin(), b.end()), b.end());for(int i = 1; i <= n; ++ i){ sum[Find(X[i])] += C[i];}int num = b.size() - 1;for(int i = 1; i <= num; ++ i)sum[i] += sum[i - 1];for(int i = 1; i <= m; ++ i){ ll ans = sum[Find(R[i])] - sum[Find(L[i]) - 1];printf("%d\n", ans);}return 0;
}

D、Is acm here?(easy)【签到】

签到题

#include <bits/stdc++.h>
#define reg register
#define ios ios::sync_with_stdio(false)
using namespace std;typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int eps = 1e-10;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;int main()
{int t;cin>>t;while(t--){string s;cin>>s;for(auto &it : s) it = tolower(it);int cnt = 0;for(int i = 0;i < s.size();++i){if(s[i] == 'a') cnt == 0 && cnt++;if(s[i] == 'c') cnt == 1 && cnt++;if(s[i] == 'm') cnt == 2 && cnt++;}cnt == 3 ? puts("YES") : puts("NO");}return 0;
}

E、填数游戏(easy)【规律】


找规律

#include<stdio.h>
int main(){int n;scanf("%d", &n);printf("%d", n + 1);
}

F、阿伟的店铺(easy - mid)【中位数】


答案就是中位数。

由于数据达到了10510^5105,我们排序的时候需要使用快速排序O(nlogn)O(nlogn)O(nlogn),或者直接用C++自带的sort函数排序。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Maxn = 1e5 + 10;
ll a[Maxn];
int main() {int n;scanf("%d", &n);for (int i = 1; i <= n; i++)a[i] = i;sort(a + 1, a + n + 1);ll ans = 0;int pos = n + 1 >> 1;for (int i = 1; i <= n; i++) {ans += abs(a[i] - a[pos]);}printf("%lld", ans);return 0;
}

G、魔法阵(mid - hard)【线性DP】

非常抱歉,本题的题目描述有些不清楚,赛前验题的时候没有发现,导致全场只有这一题没有人AC。(话说你们发现题目有问题的话可以提问呀)

其实本题就是一个非常简单的线性DP,我们需要放完所有的魔法石,但是魔法阵可以不放完,所以我们只需要考虑对于每个魔法阵来说是放置魔法石还是不放置魔法石为好,以及注意初始化的细节即可。

#include <iostream>
#include <cstdio>
#include <cstring>using namespace std;const int N = 1200;int f[N][N], w[N][N];int main() {int F, V;scanf("%d%d", &F, &V);for (int i = 1; i <= F; i++)for (int j = 1; j <= V; j++)cin >> w[j][i];memset(f, 0xcf, sizeof(f));for (int i = 1; i <= V; i++)f[i][0] = 0;f[1][1] = w[1][1];for (int i = 2; i <= V; i++)for (int j = 1; j <= F; j++)f[i][j] = max(f[i - 1][j], f[i - 1][j - 1] + w[i][j]);printf("%d\n", f[V][F]);return 0;
}

H、公益活动(mid)【简单DFS】


数据只有10,直接爆搜即可。结果没什么人做…

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;const int N = 110, INF = 0x3f3f3f3f;
int n, m;
int a[N];
int group[N][N];
int ans = INF;
bool vis[N];bool check(int g[], int gc, int x){for(int i = 0;i < gc; ++ i){if(__gcd(a[g[i]], a[x]) > 1)return false;}return true;
}void dfs(int gnum, int gc, int putnum, int now){bool flag = true;if(gnum >= ans)return ;if(putnum == n)ans = gnum;for(int i = now; i < n;++ i){//可以放下if(!vis[i] && check(group[gnum], gc, i)){vis[i] = true;group[gnum][gc] = i;dfs(gnum, gc + 1, putnum + 1, i + 1);vis[i] = false;flag = false;}}//放不了开新组if(flag)dfs(gnum + 1, 0, putnum, 0);
}int main(){scanf("%d", &n);for(int i = 0; i < n;++ i){scanf("%d", &a[i]);}dfs(1, 0, 0, 0);printf("%d\n", ans);return 0;
}

I、选拔人才(mid - hard)【贪心+优先队列 / 暴力贪心】

数据较弱,可以不适用优先队列直接暴力贪心也是可以通过的。

我们按照代码可读性从大到小排序,因为代码可读性是一个下限,我们只需要在满足代码可读性的下限的前提下找最大的可能答案即可,使用优先队列寻找最大值,更新最优解即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> p;int main()
{int t;scanf("%d", &t);while (t--){int n, k;scanf("%d%d", &n, &k);vector<p> a;for (int i = 0, b, c; i < n; ++i){scanf("%d%d", &b, &c);a.push_back(make_pair(c, b));}sort(a.begin(), a.end());reverse(a.begin(), a.end());priority_queue<int, vector<int>, greater<int> > q;ll sum = 0;ll ans = 0;for (int i = 0; i < a.size(); ++i){if (q.size() < k){q.push(a[i].second);sum += a[i].second;}else if (a[i].second > q.top()){sum += a[i].second;sum -= q.top();q.pop();q.push(a[i].second);}ans = max(ans, sum * a[i].first);}cout << ans << endl;}return 0;
}

J、2048(mid - hard)【大模拟】


直接按照题意模拟即可。

#include <bits/stdc++.h>
#define reg register
#define ios ios::sync_with_stdio(false)
using namespace std;typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int eps = 1e-10;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;struct node{int g[6][6];void movel(){for(int i = 1;i <= 5;++i){for(int j = 2;j <= 5;++j){int pos = j;while(pos > 1 && (g[i][pos-1] == 0 || g[i][pos-1] == g[i][pos])){g[i][pos-1] += g[i][pos];g[i][pos] = 0;pos--;}}}}void mover(){for(int i = 1;i <= 5;++i){for(int j = 4;j >= 1;--j){int pos = j;while(pos < 5 && (g[i][pos+1] == 0 || g[i][pos+1] == g[i][pos])){g[i][pos+1] += g[i][pos];g[i][pos] = 0;pos++;}}}}void moveu(){for(int j = 1;j <= 5;++j){for(int i = 2;i <= 5;++i){int pos = i;while(pos > 1 && (g[pos - 1][j] == 0 || g[pos - 1][j] == g[pos][j])){g[pos - 1][j] += g[pos][j];g[pos][j] = 0;pos--;}}}}void moved(){for(int j = 1;j <= 5;++j){for(int i = 4;i >= 1;--i){int pos = i;while(pos < 5 && (g[pos + 1][j] == 0 || g[pos + 1][j] == g[pos][j])){g[pos + 1][j] += g[pos][j];g[pos][j] = 0;pos++;}}}}void print(){for(int i = 1;i <= 5;++i){for(int j = 1;j <= 4;++j)printf("%d ",g[i][j]);printf("%d\n",g[i][5]);}}}mat;int main()
{#ifndef ONLINE_JUDGEfreopen("4.in","r",stdin);freopen("4.out","w",stdout);#endifint t;cin>>t;while(t--){string op;cin>>op;if(op == "Left"){mat.movel();}if(op == "Right"){mat.mover();}if(op == "Up"){mat.moveu();}if(op == "Down"){mat.moved();}int x,y;cin>>x>>y;if(mat.g[x][y] == 0) mat.g[x][y] = 2;else puts("ERROR!");// mat.print();}mat.print();return 0;
}

K、Alice和Bob的爱恨情仇(mid - hard)【构造】


我们玩几组样例就会发现如果 s<2∗ns < 2 * ns<2∗n 就一定不能找到满足条件的答案。
因为我们需要找到一个 kkk ,使得序列里所有的数都不能凑出来它,所以我们很容易就想到一个构造方法:kkk 为一个很小的值,使得其他序列里的数都比它大,这样他们加起来就更不可能凑出来它,因为我们发现小于二倍的 nnn 时就一定没有解,所以我们一定能构造出来 nnn 个 222 的序列,我们只需要将 kkk 取为比 222 小的数 —— 111 即可!。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>using namespace std;
const int N = 1e6 + 7, M = 1e7 + 7,INF = 0x3f3f3f3f;int n,s;
int main(){scanf("%d%d",&n,&s);if(s < 2 * n){puts("NO");}else {puts("YES");for(int i = 1;i < n;++i)printf("2 "),s -= 2;printf("%d\n",s);puts("1");}return 0;
}

L、石同学的树(hard)【树hash】

我们知道可以用前序遍历和中序遍历确定一个二叉树,也就是说两个结构相同的二叉树的前序遍历和中序遍历一定相同,我们需要找到结构相同的二叉树但是编号不一样,所以我们可以先来一次dfs给这颗二叉树重新赋值为DFS序,然后再找到他们的前序遍历和中序遍历,然后我们可以采取hash算法判断是否相同或者直接用set去重即可,因为本题要求的是结构不同的树的个数。set是由红黑树实现的,所有的操作都是O(logn)O(logn)O(logn),整体时间复杂度为

  • set:O(mnlogn)O(mnlogn)O(mnlogn),代码更好写一点但是多了一个常数,本来想卡一下O(mnlogn)O(mnlogn)O(mnlogn)的但是我们生成数据的 pythonpythonpython 代码生成的是一个随机的二叉树,跑10000个点就跑了十几分钟,懒得跑更大的数了hhh。

  • hash:O(nm)O(nm)O(nm)。

我们同样可以使用树 hashhashhash 来解决这个问题,树hash算法可以判重所有的树,不管是二叉树还是普通的 nnn 个节点 n−1n-1n−1 条边的树,做法比较普遍。
具体可以参考下面这篇博客:树hash - 树的同构,我在博客中使用的是几乎不可能出现 hashhashhash 冲突的一种优化 hashhashhash 算法,时间复杂度同样为 O(nm)O(nm)O(nm) 。

#include <bits/stdc++.h>
using namespace std;
int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int m;cin >> m;set <vector <int>> s;for (int i = 1; i <= m; ++i) {int n, r;cin >> n >> r;vector <pair <int, int>> e(n + 1);for (int i = 1; i <= n; ++i) {int a, b, c;cin >> a >> b >> c;e[a] = make_pair(b, c);}vector <int> id(n + 1);int tot = 0;function <void(int)> dfs1 = [&] (int cur) {if (cur == 0)return ;id[cur] = ++tot;dfs1(e[cur].first);dfs1(e[cur].second);};dfs1(r);vector <int> seq;function <void(int)> dfs2 = [&] (int cur) {if (cur == 0)return ;dfs2(e[cur].first);seq.emplace_back(id[cur]);dfs2(e[cur].second);};dfs2(r);s.insert(seq);}cout << s.size() << endl;
}

M、简单数论(hard)【欧拉函数+快速幂+拓展欧几里得+因数分解+解同余方程(doge)】


数据较弱,你只需要枚举到7就能找到答案AC了hhh
题解差不多都在题面上了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iostream>using namespace std;
typedef long long ll;
const int N = 5000007;ll n, m;
vector<int>factor;vector<int> get_factor(ll n)
{vector<int>res;for(int i = 1; i * i <= n; ++ i) {if(n % i == 0) {res.push_back(i);if(i != n / i) {res.push_back(n / i);}}}return res;
}int qpow(int a, int b, int c)
{int res = 1;while(b){if(b & 1) res = ((ll)res * a) % c;a = ((ll)a * a) % c;b >>= 1;}return res % c;
}int main()
{scanf("%lld", &n);ll phi_m = n - 1;factor = get_factor(phi_m);for(int i = 2; i < n; ++ i) {bool flag = 1;for(int j = 0; j < factor.size(); ++ j) {if(factor[j] != phi_m && qpow(i, factor[j], n) == 1) {flag = 0;break;}}if(flag) {printf("%d\n", i);break;}}return 0;
}

第十二届西南石油大学程序设计新生赛官方题解相关推荐

  1. 2023年福建农林大学程序设计校赛个人题解(无D解析)

    2023年福建农林大学程序设计校赛个人题解(无D解析) A-这是一道原题 问题解析 从绿色材料合成到金色材料. 用 w h i l e while while 循环判断材料数是否能合成,能就合,合成后 ...

  2. 第十二届蓝桥杯大赛软件赛决赛题解

    题目下载链接 注意,以下答案均为作者本人的答案,不是官方答案!!!(也就是说,可能(多半)是错的) 填空预览 25 1903 977 2607074472 试题 A: 带宽 ##[问题描述] 小蓝家的 ...

  3. 怀化学院计算机科学张显老师,怀化学院第十二届大学生计算机程序设计竞赛暨2019年湖南省第十五届大学生程序设计大赛选拔赛完美落幕...

    原标题:怀化学院第十二届大学生计算机程序设计竞赛暨2019年湖南省第十五届大学生程序设计大赛选拔赛完美落幕 2019年6月9日,由我校教务处主办,计算机科学与工程学院.怀化学院ACM协会承办的怀化学院 ...

  4. 蓝桥杯嵌入式——第十二届蓝桥杯嵌入式国赛

    蓝桥杯嵌入式--第十二届蓝桥杯嵌入式国赛 之前准备省赛的时候用的是旧版的STM32F103,从准备国赛开始就用新版STM32G431平台了,主要是想经过新版的准备学习一下HAL库以及CubeMX的使用 ...

  5. 21级爪哇程序设计新生赛(二)题解

    21级爪哇程序设计新生赛(二) 序 A 小爪的数字集合(并查集) B 小爪的得分(博弈) C 小爪的博弈(博弈) D ljc和cyj玩五子棋(模拟) E ljc和雪球(模拟) F LJC的背包(动态规 ...

  6. 第十二届蓝桥杯大赛软件赛省赛Java 大学 C 组

    第十二届蓝桥杯大赛软件赛省赛Java 大学 C 组 试题 A: ASC 试题 B: 空间 试题 C: 卡片 试题 D: 相乘 试题 E: 路径 试题 F: 时间显示 试题 G: 最少砝码 试题 H: ...

  7. 20级爪哇程序设计新生赛(一)题解

    20级爪哇程序设计新生赛题解 20级爪哇程序设计新生赛1.0(正式赛) A.The Tree Of LittleZhua(思维或者线段树) Easy Version Hard Version B.小爪 ...

  8. 第十二届蓝桥杯大赛软件赛省赛 Python 大学 A 组 试题

    第十二届蓝桥杯大赛软件赛省赛 Python 大学 A 组 试题   大家好,我叫亓官劼(qí guān jié ),在GitHub & CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~ ...

  9. 第十二届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组解析

    第十二届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组 试题 A: 空间 试题 B: 卡片 试题 C: 直线 试题 D: 货物摆放 试题 E: 路径 试题 F: 时间显示 试题 G: 砝码称重 试题 ...

最新文章

  1. 记一次解决 quill(vue-quill-editor) 编辑器中莫名多出一行“pbr/p”的过程...
  2. oracle 批量修改表结构,关于Oracle批量修改表结构相关内容的整理
  3. NAGIOS安装指南
  4. java.lang.NoClassDefFoundError
  5. 记录一次线上超时异常查询
  6. mysql重复记录大于十的数据库_面试官:在使用mysql数据库时,遇到重复数据怎么处理?...
  7. 富人和穷人的八大差异
  8. 【深度学习】简单理解Batch Normalization批标准化
  9. amd860k能装黑苹果吗_可以黑苹果,性能比同价位的GTX1650强,RX580 2048SP不香吗?...
  10. Linux下Vivado安装流程
  11. Win10设置定时关机命令简单介绍
  12. windows关闭端口方法
  13. SPSS单因素方差分析教程
  14. iOS 动画篇 - pop动画库
  15. labview虚拟心电监测系统_使用LabVIEW进行心电信号处理
  16. 东南大学破格保研挂科_兜兜转转终入四牌楼——东南大学保研心得
  17. A Creed to Live By
  18. 电压的降额 Voltage Derating
  19. douyin X-Bogus
  20. Windows 撤销快捷键“ctrl+z“失效解决方法

热门文章

  1. 实战:使用Mask-RCNN的停车位检测
  2. ACM第一名:基于轨迹感知多模态特征的视频关系检测
  3. 【OpenCV 4开发详解】轮廓面积与长度
  4. mysql5.6.20二进制安装
  5. 如何在公司局域网内访问不同网段的主机
  6. Java NIO使用及原理分析(三)
  7. echarts.js 做图表的插件
  8. linux shell的配置文件信息
  9. 用中值排序基数法实现树状结构 (转)
  10. 制作静态链接库和动态链接库