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


目录

  • Section 1.1 介绍
  • Section 1.2 提交解决方案,任务类型,特殊问题
    • 1.2.1 AcWing 1339. 你的旅途由此开始(字符串模拟)
    • 1.2.2 AcWing 1340. 贪婪的送礼者(模拟,map)
    • 1.2.3 AcWing 1341. 十三号星期五(日期模拟)
    • AcWing 1342. 断开的项链 (模拟)
  • Section 1.3 完全搜索
    • AcWing 1343. 挤牛奶(区间合并,贪心 + 模拟)
    • AcWing 1344. 转换(经典旋转类大模拟)
    • AcWing 1345. 序号命名(简单模拟)
    • AcWing 1346. 回文平方(回文 + 经典进制转换)
    • AcWing 1347. 双重回文(暴力,进制转换)
  • Section 1.4 贪心,制定解决方案
    • AcWing 1348. 搭配牛奶(简单贪心)
    • AcWing 1349. 修理牛棚(贪心 + 逆向思维 / 补集思想)
    • AcWing 1350. 密码运算(模拟)
    • AcWing 1351. 密码锁(模拟 / 容斥原理)
    • AcWing 1352. 虫洞
    • AcWing 1353. 滑雪场设计
  • Section 1.5 更多搜索技巧
    • AcWing 1354. 等差数列
    • AcWing 1355. 母亲的牛奶
  • Section 1.6 二进制数
    • AcWing 898. 数字三角形
    • AcWing 1356. 回文质数
    • AcWing 1357. 优质牛肋骨

Section 1.1 介绍

USACO Training 综述http://train.usaco.org/usacogate(USACO 97道题)
USA Computing Olympiad 是美国高校的信息学测评网站,也是美国中学生的官方竞赛网站。
美国著名在线题库,专门为信息学竞赛选手准备。
全英文界面,但有非官方的中文翻译。推荐直接阅读英语原文,既准确可靠又可提高英语水平。
网站的Training题目全面,每道题附有详细题解,可查看测试数据和运行结果,便于调试、发现错误并改正。采用章节递进的层次结构,由易到难,讲授知识、练习编程结合,题目必须依次完成,避免了只挑简单题做的行为。

第一章较为简单,属于竞赛入门题。基本不涉及太多算法和技巧,请在一周内刷完本章习题,用来巩固基础,并开始下一章的练习。

Section 1.2 提交解决方案,任务类型,特殊问题

luoguP1200、P1201、P1202、P1203

1.2.1 AcWing 1339. 你的旅途由此开始(字符串模拟)


经 典

简单的字符串模拟

#include <cstdio>
#include <algorithm>
#include <iostream>
std :: string s1, s2;
const int mod = 47;int main()
{std :: cin >> s1 >> s2;int mul1 = 1, mul2 = 1;for(int i = 0; i < s1.length(); ++ i)mul1 *= (s1[i] - 'A' + 1) % mod;for(int i = 0; i < s2.length(); ++ i)mul2 *= (s2[i] - 'A' + 1) % mod;if(mul1 % mod == mul2 % mod)puts("GO");else puts("STAY");return 0;
}

1.2.2 AcWing 1340. 贪婪的送礼者(模拟,map)


模拟,直接用map存名字和当前的钱数,每次送钱的时候,自己能剩下的就等于 money - (money / num) * num,注意如果num = 0需要特判一下。剩下的直接模拟就行了

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>using namespace std;
const int N = 50007;int n, m;
map<string, int>mp;
string names[N];
int main()
{scanf("%d", &n);for(int i = 1; i <= n; ++ i){string s;cin >> s;names[i] = s;mp[s] = 0;}for(int i = 1; i <= n; ++ i){int money, num;string s;cin >> s;scanf("%d%d", &money, &num);int remain = 0;if(num != 0)remain = money - (money / num) * num;money -= remain;mp[s] -= money;for(int j = 1; j <= num; ++ j){string name;cin >> name;mp[name] += money / num;}}for(int i = 1; i <= n; ++ i){cout << names[i] << " " << mp[names[i]] << endl;}return 0;
}

1.2.3 AcWing 1341. 十三号星期五(日期模拟)


经典日期模拟题目。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int weekday[7];int main()
{int n;cin >> n;int year = 1900, days = 0;while (n -- ){for (int i = 1; i <= 12; i ++ ){weekday[(days + 12) % 7] ++ ;days += month[i];if (i == 2)if (year % 4 == 0 && year % 100 || year % 400 == 0)days ++ ;}year ++ ;}for (int i = 5, j = 0; j < 7; i ++, j ++ )cout << weekday[i % 7] << ' ';return 0;
}

基姆拉尔森计算公式:

week=(day+2×month+[3×(month+1)÷5]+year+[year÷4]−[year÷100]+[year÷400]+1)mod7week=(day+2×month+[3×(month+1)÷5]+year+[year÷4]−[year÷100]+[year÷400]+1)mod7week=(day+2×month+[3×(month+1)÷5]+year+[year÷4]−[year÷100]+[year÷400]+1)mod7

可以直接计算出某年某月某日是星期几(好像没什么用hhh)

#include <iostream>
#include <cstdio>
#include <cstring>using namespace std;
const int N = 507;int count[N];
int week_day(int year, int month, int day)
{if (month == 1 || month == 2) month += 12, year -- ;return (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
}int main()
{int year_len = 0;cin >> year_len;for (int current_year = 1900; current_year < 1900 + year_len; current_year ++ )for (int current_month = 1; current_month <= 12; current_month ++ )count[week_day(current_year, current_month, 13)]++;cout << count[6] << " "<<count[0]<< " "<<count[1]<< " "<<count[2]<< " "<<count[3]<< " "<<count[4]<< " "<<count[5];  return 0;
}

AcWing 1342. 断开的项链 (模拟)


直接暴力O(n2)O(n^2)O(n2)枚举判断即可,但是这里需要注意的是一个类似爆搜的思路,因为w可以作为r也可以作为b,所以我们搜的时候把它变成r或者b各搜一次,最后别忘了回溯。

主要是这个数据有毒:

输入:

77
rwrwrwrwrwrwrwrwrwrwrwrwbwrwbwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwrwr

输出

74
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>using namespace std;string s, tmp;
int n, m;
int res;
int len;int slove(int x, string tmp)
{string s = tmp;int res = 2;int l = x, r = (x - 1 % len + len) % len;for(;(l + 1) % len != r && (s[l] == s[(l + 1) % len] || s[(l + 1) % len] == 'w'); l = (l + 1) % len){res ++ ;if(s[(l + 1) % len] == 'w') s[(l + 1) % len] = s[l]; }for(;(r - 1 + len) % len != l && (s[r] == s[(r - 1 % len + len) % len] || s[(r - 1 % len + len) % len] == 'w'); r = (r - 1 % len + len) % len){res ++ ;if(s[(r - 1 % len + len) % len] == 'w') s[(r - 1 % len + len) % len] = s[r];}return res;
}int main()
{cin >> n >> tmp;s = tmp;len = s.length();for(int i = 0; i < len; ++ i){res = max(res, slove(i, s));if(s[i] == 'w') {s[i] = 'r', res = max(res, slove(i, s));s[i] = 'b', res = max(res, slove(i, s));s[i] = 'w';}}cout << res << endl;return 0;
}

Section 1.3 完全搜索

luogu P1204、P1205、P1206、P1207

AcWing 1343. 挤牛奶(区间合并,贪心 + 模拟)


区间合并的经典模板题。

我们只需要按照左端点排序,然后按照题意模拟即可。

我们只需要比较右端点,维护一个连续区间的左右端点l和r,如果一个新区间的左端点和连续区间的右端点有交集(端点也算)就更新连续区间的右端点表示合并到一起,如果新区间和连续区间的右端点没有交集就更新一个连续区间的左右端点表示到达了一个新的连续区间,此时更新答案即可。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>#define x first
#define y secondusing namespace std;typedef long long ll;
typedef pair<int, int> PII;const int N = 50007;int n, m;
PII a[N];int main(){scanf("%d", &n);for(int i = 1; i <= n; ++ i){scanf("%d%d", &a[i].x, &a[i].y);}sort(a + 1, a + 1 + n);int ans1 = 0, ans2 = 0;int x = a[1].x, y = a[1].y;for(int i = 2; i <= n; ++ i){if(a[i].x <= y)y = max(y, a[i].y);else {ans1 = max(ans1, y - x);ans2 = max(ans2, a[i].x - y);x = a[i].x;y = a[i].y;}}ans1 = max(ans1, y - x);cout << ans1 << " " << ans2 << endl;return 0;
}

AcWing 1344. 转换(经典旋转类大模拟)

我们给出的是一个n∗nn*nn∗n的方阵,所以我们可以使用一个比较神奇的方法实现矩阵旋转:我们先把方阵沿着主对角线对称,然后在沿着中轴镜面对称,即可实现顺时针旋转90度的操作。

然后就是镜像翻转的操作,我们只需要从两头开始swap即可。

注:如果不是方阵的话,矩阵旋转只能使用乘上一个构造的矩阵的方法来实现,时间复杂度比较高,需要O(2n)O(2^n)O(2n)的复杂度。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>using namespace std;const int N = 5007, M = 500007;int n, m;typedef vector<string> VS;void mirror(VS & c)
{for(int i = 0; i < n; ++ i) for(int j = 0, k = n - 1; j < k ; ++ j, -- k) swap(c[i][j], c[i][k]);
}void rotate(VS& c)
{for(int i = 0; i < n; ++ i) for(int j = 0; j < i; ++ j) swap(c[i][j], c[j][i]);mirror(c);
}int solve(VS a, VS b)
{VS c = a;for(int i = 1; i <= 3; ++ i) {rotate(c);if(c == b) return i;}c = a;mirror(c);if(c == b) return 4;for(int i = 1; i <= 3; ++ i) {rotate(c);if(c == b) return 5;}if(a == b) return 6;return 7;
}string ch;int main()
{VS a, b;cin >> n;for(int i = 1; i <= n; ++ i) cin >> ch, a.push_back(ch);for(int i = 1; i <= n; ++ i)cin >> ch, b.push_back(ch);printf("%d\n", solve(a, b));return 0;
}

AcWing 1345. 序号命名(简单模拟)


直接模拟即可。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>using namespace std;const int N = 50007;int n, m;
string num, cur;int Get(char ch) {if(ch <= 'O') return (ch - 'A') / 3 + 2;if(ch <= 'S') return 7;if(ch <= 'V') return 8;return 9;
}int main()
{int cnt = 0;cin >> num;while (cin >> cur) {string tmp = "";for (auto c : cur) tmp += Get(c) + '0';if(tmp == num) {cnt ++ ;cout << cur << endl;}}if(cnt == 0) puts("NONE");return 0;
}

AcWing 1346. 回文平方(回文 + 经典进制转换)


进制转换,使用短除法实现。

注意B是1~20,十进制以上要用字母表示。

判断是否为回文字符串,可以使用双指针或者直接 reverse

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>using namespace std;const int N = 50007;int n, m;
string s;
int B;
/*
bool check(string s) {for (int i = 0, j = s.length() - 1; i< j ; ++ i, -- j) {if(s[i] != s[j]) return false;}return true;
}
*/
bool check(string s) {string ss = s;reverse(s.begin(), s.end());return ss == s;
}char get(int x)//注意B可能是10进制以上, 要用ABCD表示
{if(x <= 9) return x + '0';return x - 10 + 'A';
}string base(int x, int B)
{string res;while(x) {res += get(x % B);x /= B;}reverse (res.begin(), res.end());return res;
}int main()
{cin >> B;for (int i = 1; i <= 300; ++ i) {string num = base(i * i, B);if (check(num)) {cout << base(i, B) << " " << num << endl;}}
}

AcWing 1347. 双重回文(暴力,进制转换)


直接暴力判断即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;const int N = 50007;int n, m, s;bool check(string s)
{string res = s;reverse(s.begin(), s.end());return res == s;
}string base(int x, int B) {string res;while (x) {res += x % B;x /= B;} reverse(res.begin(), res.end());return res;
}int main()
{cin >> n >> s;for (int i = s + 1, num = 0; num < n; ++ i) {int cnt = 0;for(int j = 2; j <= 10 && cnt < 2; ++ j)if(check(base(i, j))) {cnt ++ ;}if(cnt == 2) {cout << i << endl;num ++ ;}}return 0;
}

Section 1.4 贪心,制定解决方案

luogu P1208、P1209、P1211、P1444、P3650、P2693

AcWing 1348. 搭配牛奶(简单贪心)


如果每个农民的牛奶必须取完的话,本题就是一个基础的01背包。
这里因为我们可以去一部分,所以是一个非常简单的贪心。

我们只需要按照价格排序,然后尽量买最便宜的,正确性显然。

#include <cstdio>
#include <algorithm>
#include <iostream>using namespace std;const int N = 50007;
int n, m;struct Milk
{int p, a;bool operator < (const Milk& t) const {return p < t.p;}
}milk[N];int main()
{scanf("%d%d", &m, &n);for (int i = 1; i <= n; ++ i) {scanf("%d%d", &milk[i].p, &milk[i].a);}sort(milk + 1, milk + 1 + n);int res = 0, cnt = 0;for (int i = 1; i <= n && cnt < m; ++ i) {int tmp = min(m - cnt, milk[i].a);res += milk[i].p * tmp;cnt += tmp;}cout << res << endl;return 0;
}

AcWing 1349. 修理牛棚(贪心 + 逆向思维 / 补集思想)

我们直接做的话不好做,直接贪心无法保证正确性。
我们需要使用到补集的思想,就是我们发现直接做不是很好做,我们可以使用逆向思维,
我们先用一块木板覆盖出全部,我们发现任何一种用m块木板覆盖的方案都可以用一块木板覆盖出全部,
然后中间选择间隔断开的方法转换过来,我们挑选m-1个地方断开即可。
为了让剩下的木板最小,就是让断开的木板距离最大,也就是说我们从大到小选择间隔,这样保证最优解。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 5007;int n, m;
int a[N], b[N];
int s, c;int main()
{scanf("%d%d%d", &m, &s, &c);for (int i = 0; i < c; ++ i) scanf("%d", &a[i]);sort(a, a + c);for (int i = 1; i < c; ++ i) b[i] = a[i] - a[i - 1] - 1;//3 - 1 - 1sort(b + 1, b + c, greater<int>());int res = a[c - 1] - a[0] + 1;//3 - 1 + 1for (int i = 1; i <= m - 1 && i < c; ++ i) {res -= b[i];}printf("%d\n", res);return 0;
}

AcWing 1350. 密码运算(模拟)


直接模拟即可。
注意所有的数都要判断是否是给定数组里的数。

//100~999,10~99
//check_len()位数是否合法
//check_in()是否出现的所有数字都是给定的数字#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>using namespace std;
const int N = 5007;
int n, m;
int ai[N];bool check_len(int x, int k) {return to_string(x).size() == k;
}bool check_in(int x) {while (x) {int tmp = x % 10;x /= 10;bool flag = 0;for (int i = 1; i <= n; ++ i) {if (tmp == ai[i])flag = 1;}if (flag == 0)return false;} return true;
}bool check(int a, int b) {int c = a * (b % 10), d = a * (b / 10), e =  a * b;if (!check_in(a) || !check_in(b) || !check_in(c) || !check_in(d) || !check_in(e)) return false;if (!check_len(c, 3) || !check_len(d, 3) || !check_len(e, 4)) return false;return true;
}int ans;int main()
{cin >> n;for (int i = 1; i <= n; ++ i) {cin >> ai[i];}for (int i = 100; i <= 999; ++ i) {for (int j = 10; j <= 99; ++ j) {if (check(i, j)) {ans ++ ;}}}cout << ans << endl;return 0;
}

AcWing 1351. 密码锁(模拟 / 容斥原理)

AcWing 1352. 虫洞

AcWing 1353. 滑雪场设计

Section 1.5 更多搜索技巧

luogu P1214、P1215

AcWing 1354. 等差数列

AcWing 1355. 母亲的牛奶

Section 1.6 二进制数

luogu P1216、P1217、P1218

AcWing 898. 数字三角形

AcWing 1356. 回文质数

AcWing 1357. 优质牛肋骨

【USACO training】Chapter 1 入门相关推荐

  1. USACO Training Section 1.2 双重回文数 Dual Palindrom

    题目描述 如果一个数从左往右读和从右往左读都是一样,那么这个数就叫做"回文数".例如,12321就是一个回文数,而77778就不是.当然,回文数的首和尾都应是非零的,因此0220就 ...

  2. USACO Training 综述

    USACO Training 综述 http://train.usaco.org/usacogate(USACO 97道题) USA Computing Olympiad 是美国高校的信息学测评网站, ...

  3. USACO Training Section 1.1 坏掉的项链Broken Necklace

    题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子: 第一和第二个珠子在图片中已经被作记号. 图片 A ...

  4. USACO Training Section 1.1 贪婪的送礼者Greedy Gift Givers

    P1201 [USACO1.1]贪婪的送礼者Greedy Gift Givers 题目描述 对于一群(NP个)要互送礼物的朋友,GY要确定每个人送出的钱比收到的多多少.在这一个问题中,每个人都准备了一 ...

  5. USACO Training Section 1.1 Your Ride Is Here

    题目描述 众所周知,在每一个彗星后都有一只UFO.这些UFO时常来收集地球上的忠诚支持者.不幸的是,他们的飞碟每次出行都只能带上一组支持者.因此,他们要用一种聪明的方案让这些小组提前知道谁会被彗星带走 ...

  6. USACO Training切题纪念

    USACO,一只憨态可掬的美国奶牛. 小学刚毕业的那个暑假,当稚嫩的我第一次注册完毕,进入这个美国网站时,心情是那样的急切与兴奋.首次提交并成功AC的喜悦至今记忆犹新,当屏幕上打出一行行测试点的结果, ...

  7. usaco training 4.4.1 Shuttle Puzzle 题解

    Shuttle Puzzle题解 Traditional The Shuttle Puzzle of size 3 consists of 3 white marbles, 3 black marbl ...

  8. USACO Training Section 3.2 Feed Ratios

    [url="http://ace.delos.com/usacoprob2?a=JbTv7diNbha&S=ratios"]英文原题[/url] [url="ht ...

  9. Usaco Training 刷怪旅 第三层 第六题:Ski Course Design

    说实话,一开始看上一题的时候觉得太恶心就先来做这道,所以这题其实比上一题早做出来() Farmer John has N hills on his farm (1 <= N <= 1,00 ...

最新文章

  1. JavaScript中常见的错误,你犯了几个?
  2. Boson_Netsim_6使用方法
  3. Linux内核之浅谈内存寻址
  4. python 之 append extend
  5. struts深入原理之RequestProcessor与xml
  6. ABB RAPID 在 Notepad++ 中语法高亮的实现
  7. 为什么卫星天线长得像口大锅?
  8. safari浏览器的使用tips
  9. 白鹭本地数据存储操作代码实例
  10. 华为-2025十大趋势:智能世界,触手可及.pdf(附下载链接)
  11. CMMI与Agile敏捷开发比较之一:两者的本质区别
  12. pandas object格式转float64格式
  13. php留言板系统管理,php留言板系统 更加便于网站管理
  14. Games 图形学 L2线性代数
  15. linux安装微信 安装百度网盘 下载大文件
  16. python3 scrapy中文文档_如何用python3创建scrapy项目
  17. 谷歌浏览器崩溃解决方法
  18. Win10右键菜单管理工具
  19. linux远程连接命令
  20. 自定义绘制三阶B样条曲线

热门文章

  1. 使用Python+OpenCV+detectorn2实现社交距离检测
  2. 一文概览深度学习中的激活函数
  3. 12个深度学习面试问题
  4. OpenCV直线拟合检测
  5. 链表问题2——在单链表中删除倒数第K个节点
  6. 最大子矩阵(降维处理)
  7. 如何解决diff: /../Podfile.lock: No such file or directory 的问题
  8. Linux运维之道之ENGINEER1.1(配置邮件服务器,数据库管理基础,表数据管理)
  9. google guava工具包collect包HashMultiMap基本用法
  10. SuperSocket .net服务框架