#include
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。
#include
#include
#include
#include
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,所以需要注意这些!然后不一定每局都是打完了才计分,要注意计分的时候有没打完的残局哦!
#include
#include
#include
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;
}
这个题其实是很简单的,但是我做了挺久,因为我手太生疏了,很久不做题不敲代码了(所以才有了这波寒假程序设计强化训练嘛~),但是还是想说两点:
1、这个k没确定,那就是需要遍历查找的,这个不能糊涂
2、字符串循环移位的时候,如果是对 26 取模,一定要先减 97 让它映射到 [0, 26) 的区间上去
3、哎,太久不做题了,做点基础题大家见谅……
#include
#include
#include
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
#include
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
#include
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),既然是递归,我们三步走分析:
1、递归出口:
当能够赦免的范围为0,也就是左上角正方形边长为0的时候,已经不需要赦免了,因为已经没有人可以被赦免了!所以此时当时递归的出口,也就是递归基。
2、递归函数:
每次遍历左上角,让数组值变为0,然后获得右上、右下、左下四个方位的起点,以dfs(起点,长度)为递归函数,每次完成当前赦免任务后进行上述三次递归即可!
3、递归入口:
我们设数组从0开始,那么入口就是最开始的大正方形的起点,也就是(0, 0),然后赦免的范围是整个正方形边长的一半,详情见程序。
#include
#include
#include
#include
#include
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的一道题(今年那题得分率很低的)。
关键点:
1、帮主与副帮主不参与排序
2、原来的帮派名单是按照 “职位和等级排序”的,所以最开始三个人肯定是“帮主”、“副帮主”
3、首先你需要根据帮贡排序,给每个人分配新的职位和等级
4、然后再次排序,这次就按照乐斗的:先是职位,再是等级去排序,如果都不满足,一般默认是按照输入顺序排序
今天是程序设计训练2021年寒假的第一天,是我自己觉得我的程序设计能力在这半年甚至是一年的时间里发生了很大的退步(比赛成绩不理想,做题思维和手速都慢了),所以希望让自己获得更高的程序设计与算法设计能力。在此希望鼓舞大家一起参训,纯属个人组织,难度逐步提升(近一年不专项训练了,所以难度慢慢来!)。
感谢大家阅读!