PTA Basic Level Practice 解题思路和代码,主要用的是 C++。每22题一篇博客,可以按目录来进行寻找。
文章目录
1001 害死人不偿命的(3n+1)猜想
思路:
简单的判断+循环,用一个三目运算符即可。
#include <iostream>
using namespace std;
int main()
{
int n, count = 0; // count 为步数
cin >> n;
while (n != 1) // n 为1时退出循环
{
n = n % 2 == 0 ? (n / 2) : ((3 * n + 1) / 2);
++count;
}
cout << count;
return 0;
}
1002 写出这个数
思路:
100位的整数,用哪种内置类型都表示不了,所以输入的一定是整数字符串。题目说 n 小于 1 0 100 10^{100} 10100,表明其最多只有一百位,假设每一位都是最大的9,100个9相加都只有900。所以 n 转换成数字最大也就是999。所以只需要判断三个位置上的数字即可:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string n;
int num = 0;
string cn[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
cin >> n;
for (int i = 0; i < n.size(); ++i)
num += n[i] - '0';
if (num / 100) cout << cn[num / 100] << " "; // num / 100 得到的是百位数
if (num / 10) cout << cn[(num % 100) / 10] << " "; // (num % 100) / 10 得到的是十位数
cout << cn[num % 10]; // 个位不用判断直接输出
return 0;
}
1003 我要通过!
思路:
第二点:任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串。说明形如 PAT、APATA、AAPATAA 都是正确的,即 PAT 两侧字符 A 的数量要一样多。
第三点:如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。推到一下:
- 因为 PAT 是正确的,此时 ac 均为空串,b 为 A,所以 PAAT、PAAAT 也是正确的。以此类推中间加多少个 A 都是正确的。
- 因为 APATA 是正确的,此时 abc 均为 A,所以 APAATAA 也是正确的。
- 因为 APAATAA 是正确的,此时 a 为 A,b 为 AA,c 为 AA,所以 APAAATAAA 也是正确的,以此类推,只要 P 左边是1个 A 且 T 的左右 A 的数量相同都是正确的。
- 因为 AAPATAA 是正确的,此时 ac 均为 AA,b 为 A,所以 AAPAATAAAA 也是正确的,再推一下 AAPAAATAAAAAA 也是正确的。
推了这几轮就能发现,正确的式子必须满足三点:
- 只有一个 P 和一个 T,P 在 T 的左边且中间必须有 A。
- 不能含有除 PAT 外的任何字符。
- (P 左侧的 A 的数量) * (P 和 T 中间 A 的数量) = T 右侧 A的数量。
使用 map 容器来保存每次字符出现的次数,在枚举字符的过程中,每次遇到 P 或 T 都将位置保存在相应的变量中。最后的 if 语句中的条件解释如下。
- mp[‘P’] == 1 && mp[‘T’] == 1:只有一个 P 和一个 T;
- t - p > 1:T 的位置必须在 P的右侧;
- mp[‘A’] != 0:必须含有字符 A;
- mp.size() == 3:如果出现过其他字符,map 的大小就会大于3,该条件确保只出现过 P、A、T 三个字符;
- p * (t - p - 1) == s.size():(P 左侧 A 的数量) * (P 和 T 中间 A 的数量) = T 右侧 A 的数量。
#include<iostream>
#include<map>
using namespace std;
int main()
{
int n, p = 0, t = 0; // p 保存 'P' 的位置,t 保存 'T' 出现的位置
cin >> n;
string s;
while (n--)
{
cin >> s;
map<char, int> mp;
for (int i = 0; i < s.size(); ++i)
{
++mp[s[i]]; // 当前字符个数加1
if (s[i] == 'P') p = i;
if (s[i] == 'T') t = i;
}
if (mp['P'] == 1 && mp['T'] == 1 && t - p > 1 && mp['A'] != 0
&& mp.size() == 3 && p * (t - p - 1) == s.size() - t - 1)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
1004 成绩排名
#include<iostream>
#include<map>
using namespace std;
int main()
{
int n, score, score_max = -1, score_min = 101;
string name, id, name_max, name_min, id_max, id_min;
cin >> n;
while (n--)
{
cin >> name >> id >> score;
if (score > score_max) // 更新最高分的姓名和学号
{
score_max = score;
name_max = name;
id_max = id;
}
if (score < score_min) // 更新最低分的姓名和学号
{
score_min = score;
name_min = name;
id_min = id;
}
}
cout << name_max << " " << id_max << endl;
cout << name_min << " " << id_min;
return 0;
}
1005 继续 (3n+1) 猜想
思路:
将输入的所有整数全部递推一遍,可以发现题目意思是:输出没有出现在递推过程中的所有数字,也就是没有被其他数字覆盖的数,而且得从大到小输出。可以先根据输入的整数建立一个 map<int, int>,键是数,值表示其是否出现过。值为 0 表示未出现过,为 1 表示出现过。然后遍历 map,对所有键进行一次 3n + 1 递推,这个过程中出现过的所有数字,如果在 map 中没有这个键就添加且令值为1,有则不管。最后打印所有值为 0 的键,也就是关键数字。
- 由于 map 容器会自动从小到大排序,所以从尾元素往首元素遍历。
- 输出时注意空格的处理。
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int, int> hash; // 键:值————数字:是否出现过
int k, n;
cin >> k;
while (k--) // 循环输入 k 个正整数
{
cin >> n;
hash[n] = 0; // 初始值设为0,表明尚未被覆盖
}
for (auto it = hash.cbegin(); it != hash.cend(); ++it)
{ // 遍历 map 容器
int temp = it->first; // temp 保存键
while (temp != 1) // temp 为1时退出循环
{
temp = temp % 2 == 0 ? (temp / 2) : ((3 * temp + 1) / 2);
hash[temp] = 1; // 递推过程出现的数都是被覆盖的数,将其值设为0
}
}
auto it = hash.crbegin(); // it 是指向尾元素的常迭代器
while (it->second) ++it; // it 向容器首元素方向移动直到遇见第一个关键数字
cout << it++->first; // 打印第一个关键数字,后面不跟空格
for (; it != hash.crend(); ++it) // 打印剩余的所有关键数字,其前面都需要加上空格
if (!it->second)
cout << " " << it->first;
return 0;
}
1006 换个格式输出整数
#include<iostream>
#include<map>
using namespace std;
int main()
{
int n, i;
cin >> n;
int h = n / 100, t = n % 100 / 10, u = n % 10; // h 百位数 t 十位数 u 个位数
for (i = 0; i < h; ++i) cout << 'B'; // 打印字符 B
for (i = 0; i < t; ++i) cout << 'S'; // 打印字符 S
for (i = 1; i <= u; ++i) cout << i; // 打印个位数
return 0;
}
1007 素数对猜想
思路:
对于素数算法不了解的读者可以阅读这篇文章:OJ 刷题必备知识总结(二)知识点26。在本题中,每次发现一个素数,就判断一下其与前一个素数的差值,符合题目要求计数就+1。
#include<iostream>
using namespace std;
int main()
{
int n, pre = 2, count = 0;
cin >> n;
for (int i = 2; i <= n; ++i)
{
int flag = 1; // flag 为1表明 i 是素数
for (int j = 2; j * j <= i; ++j)
if (i % j == 0)
flag = 0; // 发现其他因子,i 不是素数
if (flag)
{
if (i - pre == 2) // 当前素数与前一个素数差为2
++count;
pre = i; // pre 记录前一个素数
}
}
cout << count;
return 0;
}
1008 数组元素循环右移问题
思路:
读者可以手写题给数组平移前后的元素下标对比,就可以发现其中的规律。假设初始下标应为 a,平移后的为 b,则有:
b
=
(
a
+
m
)
%
n
b = (a + m) \% n
b=(a+m)%n
取余是因为 m 有可能大于 n(第三个测试点)。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n, m, k;
cin >> n >> m;
vector<int> vec(n, 0); // 定义大小为0的数组,初始值全0
for (int i = 0; i < n; ++i)
{
cin >> k;
vec[(i + m)% n] = k;
}
for (int i = 0; i < n - 1; ++i) // 打印整数序列
cout << vec[i] << ' ';
cout << vec[n - 1]; // 最后一个整数单独打印
return 0;
}
1009 说反话
思路:
使用 while (cin >> word) 是没问题的, 因为 PAT 的输入样例都是通过文件来读取的,读到文件结尾输入流就停止了。
#include<iostream>
#include<stack>
using namespace std;
int main()
{
stack<string> st;
string word;
while(cin >> word) // 循环读入每一个单词
st.push(word); // 单词入栈
if (!st.empty()) // 打印栈顶单词之前必须检查栈是否为空
cout << st.top(); // 打印栈顶单词
st.pop(); // 栈顶单词出栈
while(!st.empty()) // 栈空停止循环
{
cout << " " << st.top();
st.pop(); // 栈顶单词出栈
}
return 0;
}
1010 一元多项式求导
思路:
题设的一个陷阱是,如果多项式只有常数项,则应当输出 “0 0”;但如果不只有常数项,则不管常数项出现在多项式的哪个位置,求导后都不进行输出(直接跳过)。
例如 3 + 4 x − 1 + 5 x − 2 3 + 4x^{-1} +5x^{-2} 3+4x−1+5x−2,输入为3 0 4 -1 5 -2,那么求导后是 − 4 x − 2 − 10 x − 3 -4x^{-2} - 10x^{-3} −4x−2−10x−3,输出应该是 -4 -2 -10 -3,开头的 “0 0” 不要打印。
关键在于 flag 的定义,一举两得,既能拿来判定输出的格式,还能保证在没有输出的时候能正确输出 “0 0”。
#include <iostream>
using namespace std;
int main()
{
int n, k, flag = 0; // n 为系数,k 为指数,flag 为1表明有过输出
while (cin >> n >> k)
{
if (k != 0) // 非常数项才输出求导后的数字
{
if (flag) cout << " "; // 前面有输出过数字,则需要先打印一个空格
cout << n * k << " " << k - 1;
flag = 1; // 置 flag 为1表明有过输出
}
}
if (!flag) cout << "0 0"; // 如果没有输出过,打印 “0 0”
return 0;
}
1011 A+B 和 C
思路:
int 型数据能表示的范围是 [ − 2 − 31 , 2 31 − 1 ] [-2^{-31}, 2^{31} - 1] [−2−31,231−1],所以 a + b 有可能超过 int 型数据所能表示的最大范围,要用 long int 来定义三个变量。
#include <iostream>
using namespace std;
int main()
{
long int a, b, c, t;
cin >> t;
for (int i = 1; i <= t; ++i)
{
cin >> a >> b >> c;
if (a + b > c) cout << "Case #" << i << ": true" << endl;
else cout << "Case #" << i << ": false" << endl;
}
return 0;
}
1012 数字分类
思路:
题目不难,多写几个 if else 也能达到题目的要求。难点在于如何利用 C++ 的知识来解决。我采用了柳神的想法,根据余数将数字添加到对应的数组中,再集中进行处理。代码中要注意的一点是除5余1的情况,因为 j 是从0开始的,除2余数为0是加,除2余数为1才是减。
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
vector<int> vec[5]; // 定义一个二维数组
int n, k, sum1 = 0, sum2 = 0, sum3 = 0, max = 0;
cin >> n;
while (n--) // 循环输入 n 个数
{
cin >> k;
vec[k % 5].push_back(k); // 根据余数添加到对应的数组
}
for (int i = 0; i < 5; ++i) // 枚举二维数组中的所有数字
{
for (int j = 0; j < vec[i].size(); ++j)
{
if (i == 0 && vec[i][j] % 2 == 0) sum1 += vec[i][j]; // 求出除5余2的所有偶数的和
if (i == 1) sum2 += (j % 2 ? -1 : 1) * vec[i][j]; // j 从0开始的,所以要注意判定条件
if (i == 3) sum3 += vec[i][j]; // 求出除5余3的所有数的和
if (i == 4 && vec[i][j] > max) max = vec[i][j]; // 求出除5余4的数字中的最大值
}
}
for (int i = 0; i < 5; ++i)
{
if (i != 0) cout << " "; // A1 前不输出空格
if (i == 0 && sum1 == 0 || i != 0 && vec[i].size() == 0) cout << "N"; // 分类中不存在数字,输出 N
else
{
if (i == 0) cout << sum1;
if (i == 1) cout << sum2;
if (i == 2) cout << vec[2].size();
if (i == 3) cout << setiosflags(ios::fixed) << setprecision(1) << (sum3 * 1.0) / vec[3].size();
if (i == 4) cout << max;
}
}
return 0;
}
1013 数素数
思路:
这一题不能按照常规思路:找出某个范围内的所有素数,然后再去输出 P M P_M PM 到 P N P_N PN 之间的素数。因为 N 或许会很大从而出现段错误;如果直接定义一个很大的范围寻找素数还可能会导致超时,并且也并不清楚第10000个素数究竟是到多大了。
不妨这么做:从 i = 2 开始枚举所有数字,每一轮都判断 i 是否是素数,用变量 count 来标记 i 是第几个素数,一直找到 count = N - 1 时停下来,只打印 count >= M 后的所有素数。
#include <iostream>
using namespace std;
int main()
{
int m, n, count = 0; // count 统计素数的个数
cin >> m >> n;
for (int i = 2; count < n; ++i) // 因为 count 从0开始递增,所以要小于 n
{
int flag = 1; // flag 为1表明 i 是素数
for (int j = 2; j * j <= i; ++j) // 判断 i 是否为素数
if (i % j == 0) flag = 0; // 发现其他因子,i 不是素数
if (flag) ++count; // count 计数值+1
if (count >= m && flag) // 如果 count 比 m 大且 i 是素数就需要输出
{
if ((count - m + 1) % 10 != 1) cout << " "; // 每行的第一个数字前没有空格
cout << i;
if ((count - m + 1) % 10 == 0) cout << endl; // 每行的最后一个数字后要换行
}
}
return 0;
}
1014 福尔摩斯的约会
思路:
- 注意小时和分钟的输出格式。
- 这里如果你图省事儿可以混用 cin 和 printf(printf 控制输出格式更简单),这样子是可以的。但是最好不要 cout 和 printf 混用,cin 和 scanf 混用。
#include <iostream>
#include <cctype>
#include <iomanip>
using namespace std;
int main()
{
string s[7] = {"MON","TUE","WED","THU","FRI","SAT","SUN"}, s1, s2, s3, s4;
cin >> s1 >> s2 >> s3 >> s4;
int i = 0;
for (; i < s1.size() && i < s2.size(); ++i) // 寻找前面两个字符串中第一对相同的大写字母
{
if (s1[i] == s2[i] && 'A' <= s1[i] && s1[i] <= 'G')
{
cout << s[s1[i] - 'A'] << " "; // 不要忘记输出后面的空格
break; // 退出循环
}
}
++i;
for (; i < s1.size() && i < s2.size(); ++i) // 寻找前面两个字符串中第二对相同的大写字母或数字字符
{
if (s1[i] == s2[i] && (isdigit(s1[i]) || 'A' <= s1[i] && s1[i] <= 'N'))
{ // setw 指定输出的宽度为 w 个字符,setfill 指定输出宽度不足时的填充字符 c
if (isdigit(s1[i])) cout << setw(2) << setfill('0') << s1[i] - '0' << ":"; // 数字字符与大写字母的输出不一样,要区分
else cout << setw(2) << setfill('0') << s1[i] - 'A' + 10 << ":";
break;
}
}
for (i = 0; i < s3.size() && i < s4.size(); ++i)
{
if (s3[i] == s4[i] && isalpha(s3[i]))
{
cout << setw(2) << setfill('0') << i;
break;
}
}
return 0;
}
1015 德才论
思路:
这一题一定要多读几遍,然后在草稿纸上写出分类的标准。先思考出一个最初的解决方案,再一步步地进行优化。代码主要分两个部分,一个部分是根据成绩区分四类考生,另一个部分是根据成绩进行排序。
最开始我的想法是统一存入一个 vector 中,然后利用 sort 来排序。但是发现在 compare 函数中就需要写很多的代码:不仅要区分四类考生,在每类考生下又进行排序。而在 main 函数中我还是要做同样的工作,所以我索性把排序和分类彻底分开。将排序提取出来,让 compare 函数只负责排序。然后只在 main 函数中进行分类,在输入数据的时候就直接按照分数分入不同的 vector 中,输出时对每个 vector 应用 sort 后再输出即可。
经验总结:
- 先判断有没有过线,再进行考生分类,可以缩减语句,否则每个判断中都需要判断是否过线。
最后的 AC 代码如下:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct stu
{
int id, d_score, c_score, t_score; // 准考证号、德分、才分、总分
stu(int id, int d_score, int c_score)
{
this->id = id;
this->d_score = d_score;
this->c_score = c_score;
this->t_score = d_score + c_score;
}
};
vector<stu> vec[4]; // 定义二维数组
int m, l, h, d, c, i;
bool compare(struct stu p, struct stu q)
{
if (p.t_score != q.t_score) return p.t_score > q.t_score; // 总分不相同时,总分高的排在前面
else if (p.d_score != q.d_score) return p.d_score > q.d_score; // 总分相同时,德分更高的排在前面
else return p.id < q.id; // 总分和德分相同的话按照准考证号升序排列
}
int main()
{
cin >> m >> l >> h;
while (m--)
{
cin >> i >> d >> c;
struct stu temp(i, d, c);
if (d >=h && c >= h) vec[0].push_back(temp); // 第一类考生:“才德全尽”
else if (d >= h && l <= c && c < h) vec[1].push_back(temp); // 第二类考生:“德胜才”
else if (l <= d && d < h && l <= c && c < h && d >= c)
vec[2].push_back(temp); // 第三类考生:“才德兼亡”但尚有“德胜才”
else if (l <= d && d < h && l <= c) vec[3].push_back(temp); // 第四类考生
}
for (int i = 0; i < 4; ++i)
sort(vec[i].begin(), vec[i].end(), compare);
cout << vec[0].size() + vec[1].size() + vec[2].size() + vec[3].size() << endl;
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < vec[i].size(); ++j)
cout << vec[i][j].id << " " << vec[i][j].d_score << " " << vec[i][j].c_score << endl;
}
return 0;
}
1016 部分A+B
思路:
#include <iostream>
using namespace std;
int main()
{
int a, da, b, db, pa = 0, pb = 0;
cin >> a >> da >> b >> db;
while (a)
{
if (a % 10 == da) pa = pa * 10 + da;
a /= 10;
}
while (b)
{
if (b % 10 == db) pb = pb * 10 + db;
b /= 10;
}
cout << pa + pb;
return 0;
}
1017 A除以B
思路:
经验总结:
- 模拟除法的过程写出算法即可。具体的大整数除法可以参考OJ 刷题必备知识总结(二)知识点29、高精度与低精度的除法。
- 注意第二个测试用例:被除数是0时,应该输出 “0 0” 而不是输出 “0”。
- flag 的作用是,如果高位没有输出过非零数,而被除数 r 小于除数,那么该位的商0就不能输出。
#include <iostream>
using namespace std;
int main()
{
string a;
int b, flag = 0, r = 0; // r 为余数,同时也保存当前的被除数
cin >> a >> b;
for (int i = 0; i < a.size(); ++i)
{
r = r * 10 + a[i] - '0'; // 余数乘10加到该位上
if (r >= b) // 够除
{
cout << r / b; // 输出该位的商
r = r % b; // 计算余数
flag = 1; // flag = 1 表明高位输出过非零数
}
else // 不够除,则该位商为0
if (flag) cout << "0"; // 高位没输出过非零数,不需要输出0
}
if (!flag) cout << "0"; // 商为0需要打印
cout << " " << r; // 余数为0的话也需要打印
return 0;
}
1018 锤子剪刀布
思路:
a,b 分别表示每一次甲乙给出的手势,jia_win[3] 和 yi_win[3] 数组分别统计甲乙某个手势获胜的次数,下标012分别表示 BCJ,maxJ 和 maxY 分别表示甲乙获胜最多的手势对应的下标。由于获胜次数相同时按字典序输出,所以要先比较 B 和 C ,最后再比较 J。
#include <iostream>
using namespace std;
int main()
{
char a, b, c[4] = {"BCJ"};
int n, tie = 0, jia_win[3] = {0}, yi_win[3] = {0};
cin >> n;
while (n--)
{
cin >> a >> b;
if (a == b) ++tie; // 平局计数+1
else if (a == 'B' && b == 'C') ++jia_win[0]; // 甲用布赢计数+1
else if (a == 'C' && b == 'J') ++jia_win[1]; // 甲用锤赢计数+1
else if (a == 'J' && b == 'B') ++jia_win[2]; // 甲用剪赢计数+1
else if (b == 'B' && a == 'C') ++yi_win[0]; // 乙用布赢计数+1
else if (b == 'C' && a == 'J') ++yi_win[1]; // 乙用锤赢计数+1
else if (b == 'J' && a == 'B') ++yi_win[2]; // 乙用剪赢计数+1
}
cout << jia_win[0] + jia_win[1] + jia_win[2] << " " << tie << " " << yi_win[0] + yi_win[1] + yi_win[2] << endl;
cout << yi_win[0] + yi_win[1] + yi_win[2] << " " << tie << " " << jia_win[0] + jia_win[1] + jia_win[2] << endl;
int maxJ = jia_win[0] >= jia_win[1] ? 0 : 1; // 寻找甲获胜最多的手势
maxJ = jia_win[maxJ] >= jia_win[2] ? maxJ : 2;
int maxY = yi_win[0] >= yi_win[1] ? 0 : 1; // 寻找乙获胜最多的手势
maxY = yi_win[maxY] >= yi_win[2] ? maxY : 2;
cout << c[maxJ] << " " << c[maxY];
return 0;
}
1019 数字黑洞
思路:
用字符串来直接读取输入,因为 sort 函数,可以很方便的实现重新排列。将其转换为数字求差,再将差转换为字符串,然后按照格式输出即可。
经验总结:
- 注意循环的结束条件,由于一定要有输出,所以采用 do…while 而不是 while。
- 题目输入的数、求差后的结果不一定有四位,所以要在字符串前补上字符0。
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(char a, char b) { return a > b; }
int main()
{
string s, big, small, result;
cin >> s;
s.insert(0, 4 - s.size(), '0'); // s 不够四位时在前面补上字符 '0'
do
{
big = small = s;
sort(big.begin(), big.end(), cmp);
sort(small.begin(), small.end());
int a = stoi(big), b = stoi(small); // stoi() 把字符串转整数
s = to_string(a - b); // to_string() 把整数转字符串
s.insert(0, 4 - s.size(), '0');
cout << big << " - " << small << " = " << s << endl;
} while (s != "6174" && s != "0000");
return 0;
}
1020 月饼
思路:
由描述很容易知道,最大收益策略就是先把单价高的月饼卖掉,所以自然而然地想到要用上 sort 排序函数。有三个维度的数据(第三个数据 “单价” 需要单独计算),又高度绑定在一起,所以最好的办法是定义在一个结构体中。然后在 sort 函数中根据单价的大小关系进行排序。
经验总结:
- 先计算单价,再将单价乘上销量得到的结果,和放在一个表达式中的结果是一样的,不必担心精度的丢失。
sum += vec[i].unit * d;
// 上述语句等价于下面的
sum += vec[i].price / vec[i].store * d;
- 可将如下语句用两个等价的三元运算来替换:
if (d >= vec[i].store)
{
sum += vec[i].price;
d -= vec[i].store;
}
else
{
sum += vec[i].unit * d;
d = 0;
}
// 上面的 if-else 等价于下面的两个三元运算
sum += d >= vec[i].store ? vec[i].price : vec[i].unit * d;
d -= d >= vec[i].store ? vec[i].store : d;
AC 代码如下:
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
using namespace std;
struct mooncake
{
double store, price, unit; // 库存、总售价、单价
};
bool cmp(mooncake a, mooncake b) { return a.unit > b.unit; }
int main()
{
int n, d;
cin >> n >> d;
vector<mooncake> vec(n);
for (int i = 0; i < n; ++i) cin >> vec[i].store;
for (int i = 0; i < n; ++i) cin >> vec[i].price;
for (int i = 0; i < n; ++i)
vec[i].unit = vec[i].price / vec[i].store; // 计算每种月饼的单价
sort(vec.begin(), vec.end(), cmp); // 按单价从高到低排序
double sum = 0.0; // 最大收益
for (int i = 0; i < n; ++i)
{ // 计算当前的价格
sum += d >= vec[i].store ? vec[i].price : vec[i].unit * d;
d -= d >= vec[i].store ? vec[i].store : d;
}
cout << setiosflags(ios::fixed) << setprecision(2) << sum;
return 0;
}
1021 个位数统计
#include <iostream>
using namespace std;
int main()
{
string s;
cin >> s;
int digit[10] = {0};
for (int i = 0; i < s.size(); ++i)
++digit[s[i] - '0'];
for (int i = 0; i < 10; ++i)
if (digit[i])
cout << i << ":" << digit[i] << endl;
return 0;
}
1022 D进制的A+B
思路:
请读者参考OJ 刷题必备知识总结(一)知识点20、进制转换。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int a, b, c, d;
vector<int> vec;
cin >> a >> b >> d;
c = a + b;
do // 此处只能用 do...while,不能用 while,详细请参考博客
{
vec.push_back(c % d);
c /= d;
} while (c);
for (int i = vec.size() - 1; i >= 0; --i)
cout << vec[i];
return 0;
}
希望本篇博客能对你有所帮助,也希望看官能动动小手点个赞哟~~。

被折叠的 条评论
为什么被折叠?



