#include <iostream> using namespace std; const int maxn = 105; const int maxv = 1e4 + 5; int n, a[maxn], ans; bool isVis[maxv]; int main() { cin >> n; for(int i = 0;i < n;++i) { cin >> a[i]; isVis[a[i]] = true; } for(int i = 0;i < n;++i) { for(int j = i + 1;j < n;++j) { int addVal = a[i] + a[j]; if(addVal >= maxv) { continue; } isVis[addVal] = false; } } for(int i = 0;i < n;++i) { if(!isVis[a[i]]) { ans++; } } cout << ans << endl; return 0; }
须要注意的是,题目问的是:“有多少个数,刚好等于集合中另外两个(不一样的)数之和?”因此重点是知足条件的数的个数,也就是说:1 + 4 = 5 和 2 + 3 = 5 实际上是同样的!这是一个坑点,如何优雅的编程解决它呢?咱们只须要对全部的两个不一样数字的和标记成false,而后去n个数里找,有多少个数被标记成false了便可!固然,初始化的时候要所有标记成true。ios
#include <iostream> #include <vector> #include <cstring> #include <cmath> using namespace std; struct Contest { int win, lose; }; int main() { vector<Contest> C_11, C_21; int w_11 = 0, l_11 = 0; int w_21 = 0, l_21 = 0; char ch; while((ch = getchar()) != 'E') { if(ch != 'W' && ch != 'L') continue; if(ch == 'W') { w_11++; w_21++; } else if(ch == 'L') { l_11++; l_21++; } if((w_11 >= 11 || l_11 >= 11) && abs(w_11 - l_11) >= 2) { Contest c; c.win = w_11, c.lose = l_11; C_11.push_back(c); w_11 = l_11 = 0; } if((w_21 >= 21 || l_21 >= 21) && abs(w_21 - l_21) >= 2) { Contest c; c.win = w_21, c.lose = l_21; C_21.push_back(c); w_21 = l_21 = 0; } } Contest c_11, c_21; if(w_11 >= 0 || l_21 >= 0) { c_11.win = w_11; c_11.lose = l_11; C_11.push_back(c_11); } if(w_21 >= 0 || l_21 >= 0) { c_21.win = w_21; c_21.lose = l_21; C_21.push_back(c_21); } for(int i = 0;i < (int)C_11.size();++i) { cout << C_11[i].win << ':' << C_11[i].lose << endl; } for(int i = 0;i < (int)C_21.size();++i) { cout << endl << C_21[i].win << ':' << C_21[i].lose; } return 0; }
注意审题,若是某一局没有开打,就是 0:0,因此若是一局刚刚结束立马输入了字符 ‘E’,或者是一开始就输入了一个 ‘E’,则比分就是 0:0,因此须要注意这些!而后不必定每局都是打完了才计分,要注意计分的时候有没打完的残局哦!git
#include <iostream> #include <string> #include <algorithm> using namespace std; bool isValid(string str, int p1, int p2, int n, int k, string s[]) { string cur_1, cur_2; cur_1 = string(str); cur_2 = string(str); for(int i = 0;i < n;++i) cur_1[i] = ((int)cur_1[i] - 97 - k + 26) % 26 + 'a'; for(int i = 0;i < n;++i) cur_2[i] = ((int)cur_2[i] - 97 + k) % 26 + 'a'; if(cur_1 == s[p1] && cur_2 == s[p2]) return true; if(cur_1 == s[p2] && cur_2 == s[p1]) return true; return false; } int main() { int n, p1, p2, flag = 0; string s[3], ans, str = "abcd"; cin >> n; cin >> s[0] >> s[1] >> s[2]; for(int i = 0;i < 3;++i) { ans = string(s[i]); reverse(ans.begin(), ans.end()); if(i == 0) p1 = 1, p2 = 2; else if(i == 1) p1 = 0, p2 = 2; else p1 = 0, p2 = 1; for(int k = 0;k < 26;++k) { if(isValid(ans, p1, p2, n, k, s)) { flag = 1; break; } } if(flag) { break; } } cout << ans << endl; return 0; }
这个题实际上是很简单的,可是我作了挺久,由于我手太生疏了,好久不作题不敲代码了(因此才有了这波寒假程序设计强化训练嘛~),可是仍是想说两点:算法
一、这个k没肯定,那就是须要遍历查找的,这个不能糊涂
二、字符串循环移位的时候,若是是对 26 取模,必定要先减 97 让它映射到 [0, 26) 的区间上去
三、哎,过久不作题了,作点基础题你们见谅……编程
#include <iostream> #include <string> #include <cctype> using namespace std; int main() { string isbnCode; cin >> isbnCode; int base = 1, len = (int)isbnCode.length(), cnt = 0; for(int i = 0;i < len - 1;++i) { if(isdigit(isbnCode[i])) { cnt += base * (isbnCode[i] - '0'); base++; } } cnt %= 11; char sign = cnt == 10 ? 'X' : cnt + '0'; if(isbnCode[len - 1] != sign) { isbnCode[len - 1] = sign; cout << isbnCode << endl; } else { cout << "Right" << endl; } return 0; }
这个题是大一的时候作过的题目,时间久远,拿来练练手。好在只作了5分钟,否则我该切腹自尽了……这题我写的自认算是比较简洁啦,没什么易错点,照着模拟便可。数组
#include <iostream> #include <string> using namespace std; const int inf = 0x3f3f3f3f; bool isPrime(int n) { if(n < 2) return false; for(int i = 2;i * i <= n;++i) { if(n % i == 0) { return false; } } return true; } int main() { string str; cin >> str; int isVis[26], maxn = 0, minn = inf, len = str.length(); for(int i = 0;i < 26;++i) { isVis[i] = 0; } for(int i = 0;i < len;++i) { int cur = str[i] - 'a'; isVis[cur]++; } for(int i = 0;i < 26;++i) { if(!isVis[i]) continue; if(isVis[i] > maxn) maxn = isVis[i]; if(isVis[i] < minn) minn = isVis[i]; } if(isPrime(maxn - minn)) { cout << "Lucky Word" << endl << maxn - minn << endl; } else { cout << "No Answer" << endl << 0 << endl; } return 0; }
#include <iostream> #include <cstring> using namespace std; const int maxn = 1 << 11; int n, a[maxn][maxn], l; void dfs(int r, int c, int len) { if(len <= 0) return ; for(int i = r;i < r + len;++i) for(int j = c;j < c + len;++j) a[i][j] = 0; dfs(r, c + len, len >> 1); dfs(r + len, c, len >> 1); dfs(r + len, c + len, len >> 1); } int main() { cin >> n; l = 1 << n; for(int i = 0;i < l;++i) for(int j = 0;j < l;++j) a[i][j] = 1; dfs(0, 0, l >> 1); for(int i = 0;i < l;++i) { for(int j = 0;j < l;++j) cout << a[i][j] << ' '; cout << endl; } return 0; }
这题很明显是个递归,每次都是让左上角赦免(全为0),既然是递归,咱们三步走分析:markdown
一、递归出口:
当可以赦免的范围为0,也就是左上角正方形边长为0的时候,已经不须要赦免了,由于已经没有人能够被赦免了!因此此时当时递归的出口,也就是递归基。app
二、递归函数:
每次遍历左上角,让数组值变为0,而后得到右上、右下、左下四个方位的起点,以dfs(起点,长度)为递归函数,每次完成当前赦免任务后进行上述三次递归便可!ide
三、递纳入口:
咱们设数组从0开始,那么入口就是最开始的大正方形的起点,也就是(0, 0),而后赦免的范围是整个正方形边长的一半,详情见程序。函数
#include <iostream> #include <algorithm> #include <string> #include <map> #include <vector> using namespace std; const int maxn = 120; struct Member { string name; string work; int contribute; int rank; int mapper_work; int id; }members[maxn]; bool cmp1(Member m1, Member m2) { if(m1.contribute != m2.contribute) return m1.contribute > m2.contribute; return m1.id < m2.id; } bool cmp2(Member m1, Member m2) { if(m1.mapper_work != m2.mapper_work) return m1.mapper_work < m2.mapper_work; else if(m1.rank != m2.rank) return m1.rank > m2.rank; else return m1.id < m2.id; } int main() { map<string, int> mp; mp["BangZhu"] = 0, mp["FuBangZhu"] = 1, mp["HuFa"] = 2; mp["ZhangLao"] = 3, mp["TangZhu"] = 4, mp["JingYing"] = 5, mp["BangZhong"] = 6; int n, r3 = 2, r4 = 4, r5 = 7, r6 = 25; cin >> n; for(int i = 0;i < n;++i) { cin >> members[i].name >> members[i].work >> members[i].contribute >> members[i].rank; members[i].mapper_work = mp[members[i].work]; members[i].id = i + 1; } sort(members + 3, members + n, cmp1); for(int i = 3;i < n;++i) { if(r3 > 0) { members[i].work = "HuFa"; r3--; } else if(r4 > 0) { members[i].work = "ZhangLao"; r4--; } else if(r5 > 0) { members[i].work = "TangZhu"; r5--; } else if(r6 > 0) { members[i].work = "JingYing"; r6--; } else members[i].work = "BangZhong"; members[i].mapper_work = mp[members[i].work]; } sort(members, members + n, cmp2); for(int i = 0;i < n;++i) { cout << members[i].name << ' ' << members[i].work << ' ' << members[i].rank << endl; } return 0; }
这题标准的模拟,能够用来训练天梯赛的L2的一道题(今年那题得分率很低的)。atom
关键点:
一、帮主与副帮主不参与排序
二、原来的帮派名单是按照 “职位和等级排序”的,因此最开始三我的确定是“帮主”、“副帮主”
三、首先你须要根据帮贡排序,给每一个人分配新的职位和等级
四、而后再次排序,此次就按照乐斗的:先是职位,再是等级去排序,若是都不知足,通常默认是按照输入顺序排序
今天是程序设计训练2021年寒假的第一天,是我本身以为个人程序设计能力在这半年甚至是一年的时间里发生了很大的退步(比赛成绩不理想,作题思惟和手速都慢了),因此但愿让本身得到更高的程序设计与算法设计能力。在此但愿鼓舞你们一块儿参训,纯属我的组织,难度逐步提高(近一年不专项训练了,因此难度慢慢来!)。
感谢你们阅读!