问题描述
分析
代码
#include
using namespace std;
int main() {
int a, b;
cin >> a >> b;
int c = a + b;
string num = to_string(c);
string res;
for (int i = num.size() - 1, j = 0; i >= 0; i--) {
res = num[i] + res;
j++;
if (j % 3 == 0 && i && num[i - 1] != '-') res = ',' + res;
}
cout << res << endl;
return 0;
}
问题描述
分析
代码
#include
using namespace std;
int main() {
string num;
cin >> num;
int sum = 0;
for (auto c : num) sum += c - '0';
string str = to_string(sum);
string name[] = {
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"
};
for (auto c : str) cout << name[c - '0'] << ' ';
return 0;
}
问题描述
分析
代码
#include
using namespace std;
int n;
int main() {
string open_id, open_time;
string close_id, close_time;
cin >> n;
for (int i = 0; i < n; i++) {
string id, in_time, out_time;
cin >> id >> in_time >> out_time;
// 更新开门的人
if (!i || in_time < open_time) {
open_id = id;
open_time = in_time;
}
// 更新关门的人
if (!i || out_time > close_time) {
close_id = id;
close_time = out_time;
}
}
cout << open_id << ' ' << close_id << endl;
return 0;
}
问题描述
分析
代码
#include
using namespace std;
const int N = 1010;
int n;
string name[N], pwd[N]; // 记录被修改的记录的用户名和密码
string change(string str) {
string res;
for (auto c : str) {
if (c == '1') res += '@';
else if (c == '0') res += '%';
else if (c == 'l') res += 'L';
else if (c == 'O') res += 'o';
else res += c;
}
return res;
}
int main() {
cin >> n;
int m = 0; // 需要修改的用户的数量
for (int i = 0; i < n; i++) {
string cur_name, cur_pwd;
cin >> cur_name >> cur_pwd;
string changed_pwd = change(cur_pwd);
if (cur_pwd != changed_pwd) {
name[m] = cur_name;
pwd[m] = changed_pwd;
m++;
}
}
if (!m) {
if (n == 1) puts("There is 1 account and no account is modified");
else printf("There are %d accounts and no account is modified\n", n);
} else {
cout << m << endl;
for (int i = 0; i < m; i++) cout << name[i] << ' ' << pwd[i] << endl;
}
return 0;
}
问题描述
分析
代码
#include
using namespace std;
int main() {
int n;
cin >> n;
string girl_name, girl_id; // 女生第一名的信息
int girl_score;
string boy_name, boy_id; // 男生倒数第一名的信息
int boy_score;
for (int i = 0; i < n; i++) {
string name, sex, id;
int score;
cin >> name >> sex >> id >> score;
if (sex == "F") {
if (girl_name.empty() || girl_score < score) {
girl_name = name;
girl_id = id;
girl_score = score;
}
} else {
if (boy_name.empty() || boy_score > score) {
boy_name = name;
boy_id = id;
boy_score = score;
}
}
}
if (girl_name.empty()) puts("Absent");
else cout << girl_name << ' ' << girl_id << endl;
if (boy_name.empty()) puts("Absent");
else cout << boy_name << ' ' << boy_id << endl;
if (girl_name.size() && boy_name.size()) cout << girl_score - boy_score << endl;
else cout << "NA" << endl;
return 0;
}
问题描述
分析
b
中存在的字符,然后遍历字符串a
中的所有字符c
,如果c
在哈希表中没有出现,则将c
加到结果中即可。代码
#include
#include
using namespace std;
int main() {
string a, b;
getline(cin, a);
getline(cin, b);
unordered_set<char> S;
for (auto c : b) S.insert(c);
string res;
for (auto c : a)
if (!S.count(c))
res += c;
cout << res << endl;
return 0;
}
问题描述
分析
将每个单词切分出来,然后全部转化为小写,与此同时使用哈希表统计每个单词出现的次数。
之后遍历哈希表,找到出现次数最多且字典序最小的单词输出即可。
代码
#include
#include
using namespace std;
bool check(char c) {
if (c >= '0' && c <= '9') return true;
if (c >= 'a' && c <= 'z') return true;
if (c >= 'A' && c <= 'Z') return true;
return false;
}
char to_lower(char c) {
if (c >= 'A' && c <= 'Z') return c + 'a' - 'A';
return c;
}
int main() {
string str;
getline(cin, str);
unordered_map<string, int> hash; // (单词, 出现次数)
for (int i = 0; i < str.size(); i++)
if (check(str[i])) {
string word;
int j = i;
while (j < str.size() && check(str[j])) word += to_lower(str[j++]);
hash[word]++;
i = j;
}
string word;
int cnt = -1;
for (auto item : hash)
if (item.second > cnt || item.second == cnt && item.first < word) {
word = item.first;
cnt = item.second;
}
cout << word << ' ' << cnt << endl;
return 0;
}
问题描述
分析
代码
#include
using namespace std;
int main() {
string a, b, c, d;
cin >> a >> b >> c >> d;
int k = 0;
while (true) {
if (a[k] == b[k] && a[k] >= 'A' && a[k] <= 'G') break;
k++;
}
char weekdays[7][4] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
printf("%s ", weekdays[a[k] - 'A']);
k++;
while (true) {
if (a[k] == b[k] && (a[k] >= '0' && a[k] <= '9' || a[k] >= 'A' && a[k] <= 'N')) break;
k++;
}
printf("%02d:", a[k] <= '9' ? a[k] - '0' : a[k] - 'A' + 10);
for (int i = 0; ; i++)
if (c[i] == d[i] && (c[i] >= 'a' && c[i] <= 'z' || c[i] >= 'A' && c[i] <= 'Z')) {
printf("%02d", i);
break;
}
return 0;
}
问题描述
分析
因为需要按照人名的字典序输出每个人的信息,因此可以使用map
记录每个人的信息,每个人可能有多条通话记录,使用vector
记录这些信息,每条信息用一个结构体存储。
为了方便计算时间之差,这里将所有时间转化为相对于当月零时零分过去的时间。这样也方便排序。
为了方便计算任意两个时刻的花费,可以使用前缀和数组的技巧。
另外还需要将美分转化为美元。
代码
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 1010, M = 31 * 1440 + 10;
int n;
int cost[24]; // 每个时间段的花费
double sum[M]; // 从当月1号00:00开始到每个时刻所花费的钱数, 例如sum[1]表示00:00~00:01的花费
struct Record {
int minutes; // 从当月1号00:00经过的时间
string state;
string format_time;
bool operator< (const Record& w) const {
return minutes < w.minutes;
}
};
map<string, vector<Record>> persons;
int main() {
for (int i = 0; i < 24; i++) scanf("%d", &cost[i]);
// 例如i = 60, 表示sum[60] = sum[59] + cost[59 / 60] / 100.0;
for (int i = 1; i < M; i++) sum[i] = sum[i - 1] + cost[(i - 1) % 1440 / 60] / 100.0; // 美分转化为美元
// 处理输入
cin >> n;
char name[25], state[10], format_time[20];
int month, day, hour, minute;
for (int i = 0; i < n; i++) {
scanf("%s %d:%d:%d:%d %s", name, &month, &day, &hour, &minute, state);
sprintf(format_time, "%02d:%02d:%02d", day, hour, minute);
int minutes = (day - 1) * 1440 + hour * 60 + minute;
persons[name].push_back({minutes, state, format_time});
}
// 依次处理每个人
for (auto &person : persons) {
auto name = person.first;
auto records = person.second;
sort(records.begin(), records.end());
double total = 0; // 总花费
for (int i = 0; i + 1 < records.size(); i++) {
auto a = records[i], b = records[i + 1];
if (a.state == "on-line" && b.state == "off-line") {
if (!total) printf("%s %02d\n", name.c_str(), month);
cout << a.format_time << ' ' << b.format_time;
double c = sum[b.minutes] - sum[a.minutes];
printf(" %d $%.2lf\n", b.minutes - a.minutes, c);
total += c;
}
}
if (total) printf("Total amount: $%.2lf\n", total);
}
return 0;
}
问题描述
分析
使用一个优先队列存储m
个窗口的空闲时间点 。
读入所有的人,按照到达时间进行排序,然后依次处理每个人,每次 从优先队列中弹出一个时间w
,这代表在w
时刻有一个窗口空闲,此时可以有一个人到这个窗口,计算该人的等待时间,加到答案中。
如果当前考虑的人达到的时间超过了下午五点,后面的人就不需要考察了。
另外需要注意即使有窗口空闲,但可能人还没来,因此窗口此时需要等待顾客。
代码
#include
#include
#include
using namespace std;
const int N = 10010;
int n, m;
struct Person {
int arrive_time;
int service_time;
bool operator< (const Person& t) const {
return arrive_time < t.arrive_time;
}
} persons[N];
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
int hour, minute, second, service_time;
scanf("%d:%d:%d %d", &hour, &minute, &second, &service_time);
service_time = min(service_time, 60);
persons[i] = {hour * 3600 + minute * 60 + second, service_time * 60};
}
priority_queue<int, vector<int>, greater<int>> windows; // 优先队列存储窗口
for (int i = 0; i < m; i++) windows.push(8 * 3600);
sort(persons, persons + n);
int sum = 0, cnt = 0; // sum: 等待时间; cnt: 服务的人数
for (int i = 0; i < n; i++) {
auto person = persons[i];
int w = windows.top();
windows.pop();
if (person.arrive_time > 17 * 3600) break;
int start_time = max(person.arrive_time, w); // 开始服务该人的时间
sum += start_time - person.arrive_time;
cnt++;
windows.push(start_time + person.service_time); // 下次窗口空闲的时间
}
printf("%.1lf\n", (double)sum / cnt / 60);
return 0;
}
问题描述
分析
代码
问题描述
分析
总体思路是首先将两个字符串转为题目对应形式,然后对比是否相同后输出。具体转化步骤如下:
(1)找到小数点的位置,并将小数点去掉;
(2)去掉前导0;
(3)对齐到n位;
(4)拼接成题目要求字符串返回
代码
#include
using namespace std;
string change(string a, int n) {
// 第一步:找到小数点的位置,并将小数点去掉
int k = a.find('.');
if (k == -1) a += '.', k = a.find('.');
a = a.substr(0, k) + a.substr(k + 1);
// 第二步:去掉前导0
while (a.size() && a[0] == '0') a = a.substr(1), k--;
if (a.empty()) k = 0; // 说明a是0
// 第三步:对齐到n位
if (a.size() >= n) a = a.substr(0, n);
else a += string(n - a.size(), '0');
// 第四步:拼接成题目要求字符串返回
return "0." + a + "*10^" + to_string(k);
}
int main() {
int n;
string a, b;
cin >> n >> a >> b;
string A = change(a, n);
string B = change(b, n);
if (A == B) cout << "YES " << A << endl;
else cout << "NO " << A << ' ' << B << endl;
return 0;
}
问题描述
分析
分为如下步骤:
(1)如果是负数,先输出一个负号;
(2)得到底数和指数部分,并让小数点向前移动一位,指数加一;
(3)根据指数的整数得到结果。
代码
#include
using namespace std;
int main() {
string s;
cin >> s;
if (s[0] == '-') cout << '-';
// 例如: +1.23400E-03, 则会得到 a=123400, p=-2
int k = s.find('E');
string a = s[1] + s.substr(3, k - 3);
int p = stoi(s.substr(k + 1));
p++;
if (p <= 0) a = "0." + string(-p, '0') + a;
else if (p >= a.size()) a += string(p - a.size(), '0');
else a = a.substr(0, p) + '.' + a.substr(p);
cout << a << endl;
return 0;
}
问题描述
分析
我们需要求出给定多个字符串的最长公共后缀。
可以从后向前遍历第一个字符串,然后考察其他字符串对应位置是否和第一个字符串对应位置相同。
代码
#include
using namespace std;
const int N = 110;
int n;
string s[N];
int main() {
cin >> n;
getchar();
for (int i = 0; i < n; i++) getline(cin, s[i]);
string res;
for (int i = s[0].size() - 1, j = 1; i >= 0; i--, j++) { // j代表考察的是倒数第j个字母
bool flag = false;
char c = s[0][i];
for (int i = 1; i < n; i++) {
string str = s[i];
if (j > str.size() || str[str.size() - j] != c) {
flag = true;
break;
}
}
if (flag) break;
res = c + res;
}
if (res.empty()) cout << "nai" << endl;
else cout << res << endl;
return 0;
}
问题描述
分析
因为最多九位,我们将其拆为三个数字进行读,使用work
函数返回一个四位数的读法。
两个四位数之间,如果后面一个四位数小于1000
,说明该四位数千位是0
,如果此时答案的结尾不是0
,这加上0
。
代码
#include
#include
using namespace std;
string num1[] = {
"ling", "yi", "er", "san", "si",
"wu", "liu", "qi", "ba", "jiu"
};
bool check(string s) {
return s.size() >= 5 && s.substr(s.size() - 5) == "ling ";
}
// 给定一个非零的四位数,返回其读法
// 1030: yi Qian ling san Shi
// 521: wu Bai er Shi yi
// 2008: er Qain ling ba
// 900: jiu Bai
string work(int n) {
vector<int> num;
while (n) num.push_back(n % 10), n /= 10;
string num2[] = {"", "Shi", "Bai", "Qian"};
string res;
for (int i = num.size() - 1; i >= 0; i--) {
int t = num[i];
if (t) res += num1[t] + " "; // t不是0
else if (!check(res)) res += "ling "; // t是0,当前res最后不是0,则增加一个0
if (t && i) res += num2[i] + " "; // t不是0, 并且不是最低位
}
if (check(res)) res = res.substr(0, res.size() - 5); // 最后的0需要删除
return res;
}
int main() {
int n;
cin >> n;
if (!n) puts("ling");
else {
if (n < 0) cout << "Fu ", n = -n;
vector<int> num;
while (n) num.push_back(n % 10000), n /= 10000;
string num3[] = {"", "Wan", "Yi"};
string res;
for (int i = num.size() - 1; i >= 0; i--) {
int t = num[i];
if (t < 1000) { // 此时千位为0
if (res.size() && !check(res)) res += "ling ";
}
if (t) res += work(t); // 如果t不是0,则加上这四位的读法
if (t && i) res += num3[i] + " "; // 如果t不是0, 并且不是最低位
}
if (check(res)) res = res.substr(0, res.size() - 5);
res.pop_back();
cout << res << endl;
}
return 0;
}
问题描述
分析
a、b
,当a
中存在某个字符,但b
中不存在时,说明该字符对应的键损坏,输出即可,并标记为已经输出,防止多次输出。代码
#include
using namespace std;
int main() {
string a, b;
cin >> a >> b;
bool st[256] = {0};
b += '#'; // 这样就不用特判b的结束位置了
for (int i = 0, j = 0; i < a.size(); i++) {
char x = toupper(a[i]), y = toupper(b[j]);
if (x == y) j++;
else {
if (!st[x]) cout << x, st[x] = true;
}
}
return 0;
}
问题描述
分析
try catch
解决。代码
#include
using namespace std;
int main() {
int n;
cin >> n;
int cnt = 0; // 合法数据个数
double sum = 0; // 合法数据之和
while (n--) {
string num;
cin >> num;
double x;
bool success = true;
try {
size_t idx; // 记录num转化为浮点数使用到了多少位
x = stof(num, &idx);
if (idx < num.size()) // 说明可能是"123ab"的形式
success = false;
} catch (...) {
success = false;
}
if (x < -1000 || x > 1000) success = false;
int k = num.find('.');
if (k != -1 && num.size() - k > 3) success = false;
if (success) cnt++, sum += x;
else printf("ERROR: %s is not a legal number\n", num.c_str());
}
if (cnt > 1) printf("The average of %d numbers is %.2lf\n", cnt, sum / cnt);
else if (cnt == 1) printf("The average of 1 number is %.2lf\n", sum);
else printf("The average of 0 numbers is Undefined\n");
return 0;
}
问题描述
分析
代码
#include
#include
using namespace std;
const int N = 1010;
int m, n, s;
string name[N];
int main() {
cin >> m >> n >> s;
for (int i = 1; i <= m; i++) cin >> name[i];
unordered_set<string> hash;
int k = s;
while (k <= m) {
if (hash.count(name[k])) k++;
else {
hash.insert(name[k]);
cout << name[k] << endl;
k += n;
}
}
if (hash.empty()) puts("Keep going...");
return 0;
}
问题描述
分析
vector
中,排序后输出即可。代码
#include
#include
#include
#include
using namespace std;
struct School {
string name;
int cnt;
double sum;
School() : cnt(0), sum(0) {}
bool operator< (const School &t) const {
if (sum != t.sum) return sum > t.sum;
if (cnt != t.cnt) return cnt < t.cnt;
return name < t.name;
}
};
int main() {
int n;
cin >> n;
unordered_map<string, School> schools;
for (int i = 0; i < n; i++) {
string id, sch;
double grade;
cin >> id >> grade >> sch;
for (auto &c : sch) c = tolower(c);
if (id[0] == 'B') grade /= 1.5;
else if (id[0] == 'T') grade *= 1.5;
schools[sch].name = sch;
schools[sch].cnt++;
schools[sch].sum += grade;
}
vector<School> res;
for (auto item : schools) {
item.second.sum = (int) (item.second.sum + 1e-8); // 浮点精度问题
res.push_back(item.second);
}
sort(res.begin(), res.end());
cout << res.size() << endl;
int rank = 1;
for (int i = 0; i < res.size(); i++) {
auto s = res[i];
if (i && s.sum != res[i - 1].sum) rank = i + 1;
printf("%d %s %d %d\n", rank, s.name.c_str(), (int)s.sum, s.cnt);
}
return 0;
}
问题描述
分析
使用结构体存储每一条记录,使用vector
存储所有记录。
对于不同类型的查询,直接遍历一遍所有记录,将符合条件的记录存储下来,最后得到统计结果输出即可。
代码
#include
#include
#include
#include
using namespace std;
const int N = 10010;
int n, m;
struct Student {
string info;
string level; // 级别
string room; // 考场
string date; // 考试时间
string id; // 考号
int grade;
bool operator< (const Student &t) const {
if (grade != t.grade) return grade > t.grade;
return info < t.info;
}
} p[N];
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
string info;
int grade;
cin >> info >> grade;
p[i].info = info;
p[i].level = info.substr(0, 1);
p[i].room = info.substr(1, 3);
p[i].date = info.substr(4, 6);
p[i].id = info.substr(10);
p[i].grade = grade;
}
for (int i = 1; i <= m; i++) {
string t, c;
cin >> t >> c;
printf("Case %d: %s %s\n", i, t.c_str(), c.c_str());
if (t == "1") {
vector<Student> students;
for (int i = 0; i < n; i++)
if (p[i].level == c)
students.push_back(p[i]);
sort(students.begin(), students.end());
if (students.empty()) puts("NA");
else {
for (auto &s : students)
printf("%s %d\n", s.info.c_str(), s.grade);
}
} else if (t == "2") {
int cnt = 0, sum = 0;
for (int i = 0; i < n; i++)
if (p[i].room == c) {
cnt++;
sum += p[i].grade;
}
if (!cnt) puts("NA");
else printf("%d %d\n", cnt, sum);
} else {
unordered_map<string, int> hash;
for (int i = 0; i < n; i ++ )
if (p[i].date == c)
hash[p[i].room] ++ ;
vector<pair<int, string>> rooms;
for (auto item : hash) rooms.push_back({-item.second, item.first});
sort(rooms.begin(), rooms.end());
if (rooms.empty()) puts("NA");
else
for (auto room : rooms)
printf("%s %d\n", room.second.c_str(), -room.first);
}
}
return 0;
}