文章目录
数字反转(升级版)
题目背景
以下为原题面,仅供参考:
给定一个数,请将该数各个位上数字反转得到一个新数。
这次与 NOIp2011 普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。整数反转是将所有数位对调;小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分;分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母;百分数的分子一定是整数,百分数只改变数字部分。整数新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零;小数新数的末尾不为 0 0 0(除非小数部分除了 0 0 0 没有别的数,那么只保留1个 0 0 0);分数不约分,分子和分母都不是小数(约分滴童鞋抱歉了,不能过哦。输入数据保证分母不为 0 0 0),本次没有负数。
题目描述
给定一个数,请将该数各个位上数字反转得到一个新数。
这次与 NOIp2011 普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。
-
整数反转是将所有数位对调。
-
小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分。
-
分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母。
-
百分数的分子一定是整数,百分数只改变数字部分。
输入格式
一个实数 s s s
输出格式
一个实数,即 s s s 的反转数
样例 #1
样例输入 #1
5087462
样例输出 #1
2647805
样例 #2
样例输入 #2
600.084
样例输出 #2
6.48
样例 #3
样例输入 #3
700/27
样例输出 #3
7/72
样例 #4
样例输入 #4
8670%
样例输出 #4
768%
提示
【数据范围】
- 对于 25 % 25\% 25% 的数据, s s s 是整数,不大于 20 20 20 位;
- 对于 25 % 25\% 25% 的数据, s s s 是小数,整数部分和小数部分均不大于 10 10 10 位;
- 对于 25 % 25\% 25% 的数据, s s s 是分数,分子和分母均不大于 10 10 10 位;
- 对于 25 % 25\% 25% 的数据, s s s 是百分数,分子不大于 19 19 19 位。
【数据保证】
-
对于整数翻转而言,整数原数和整数新数满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数和原来的数字的最高位数字不应为零。
-
对于小数翻转而言,其小数点前面部分同上,小数点后面部分的形式,保证满足小数的常见形式,也就是末尾没有多余的 0 0 0(小数部分除了 0 0 0 没有别的数,那么只保留 1 1 1 个 0 0 0。若反转之后末尾数字出现 0 0 0,请省略多余的 0 0 0)
-
对于分数翻转而言,分数不约分,分子和分母都不是小数。输入的分母不为 0 0 0。与整数翻转相关规定见上。
-
对于百分数翻转而言,见与整数翻转相关内容。
数据不存在负数。
模拟
#include<bits/stdc++.h> // 引入标准库,提供各种功能的支持
using namespace std; // 使用标准命名空间
int main() {
string a; // 定义一个字符串变量,用于存储输入的数字
cin >> a; // 从标准输入读取一个字符串
vector<char> s(a.begin(), a.end()); // 将字符串转换为字符向量
int flag = 0; // 标志位,用于判断输入是哪种类型的数字
int k = 0; // 用于标记小数点或分数线在字符串中的位置
// 检查最后一个字符是否为百分号,如果是,则处理百分数
if (s.back() == '%') {
reverse(s.begin(), s.end() - 1); // 反转除百分号外的所有字符
// 移除前导零并处理特殊情况
for (int i = 0; i < s.size() - 1; i++) {
if (s[i] != '0')
break;
if (i == s.size() - 2 && s[i] == '0') {
cout << "0%"; // 如果整个数字部分都是0,则输出0%
return 0;
}
}
int i = 0;
while (s[i] == '0') i++; // 跳过前导零
for (; i < s.size(); i++) // 输出反转后的数字部分
cout << s[i];
return 0;
}
// 遍历字符串,查找小数点或分数线的位置
for (int i = 0; i < s.size(); i++) {
if (s[i] == '.') {
flag = 1; // 标记为小数
k = i; // 记录小数点的位置
break;
}
if (s[i] == '/') {
flag = 2; // 标记为分数
k = i; // 记录分数线的位置
break;
}
}
// 根据标志位处理不同类型的数字反转
if (flag == 1) { // 小数
// 处理整数部分
vector<char> q(a.begin(), a.begin() + k);
// 反转整数部分并移除末尾零
for (int i = 0; i < q.size(); i++) {
if (q[i] != '0')
break;
if (i == q.size() - 1 && q[i] == '0') {
cout << "0";
}
}
while (q.size() > 0 && q.back() == '0') q.pop_back();
reverse(q.begin(), q.end()); // 反转整数部分
// 输出整数部分
for (int i = 0; i < q.size(); i++)
cout << q[i];
cout << '.'; // 输出小数点
// 处理小数部分
vector<char> h(a.begin() + k + 1, a.end());
for (int i = 0; i < h.size(); i++) {
if (h[i] != '0')
break;
if (i == h.size() - 1 && h[i] == '0') {
cout << '0';
return 0;
}
}
reverse(h.begin(), h.end()); // 反转小数部分
while (h.size() > 0 && h.back() == '0') h.pop_back();
// 输出小数部分
for (int i = 0; i < h.size(); i++)
cout << h[i];
} else if (flag == 2) { // 分数
// 处理分子部分
vector<char> q(a.begin(), a.begin() + k);
// 反转分子部分并移除末尾零
for (int i = 0; i < q.size(); i++) {
if (q[i] != '0')
break;
if (i == q.size() - 1 && q[i] == '0') {
cout << "0";
}
}
while (q.size() > 0 && q.back() == '0') q.pop_back();
reverse(q.begin(), q.end()); // 反转分子部分
// 输出分子部分
for (int i = 0; i < q.size(); i++)
cout << q[i];
cout << '/'; // 输出分数线
// 处理分母部分
vector<char> h(a.begin() + k + 1, a.end());
while (h.size() > 0 && h.back() == '0') h.pop_back(); // 移除末尾零
reverse(h.begin(), h.end()); // 反转分母部分
// 输出分母部分
for (int i = 0; i < h.size(); i++)
cout << h[i];
} else { // 整数
// 反转整数部分并移除前导零
for (int i = 0; i < s.size(); i++) {
if (s[i] != '0')
break;
if (i == s.size() - 1 && s[i] == '0') {
cout << "0";
}
}
while (s.size() > 0 && s.back() == '0') s.pop_back();
reverse(s.begin(), s.end()); // 反转整数部分
// 输出整数部分
for (int i = 0; i < s.size(); i++)
cout << s[i];
}
return 0; // 程序结束
}
代码的主要逻辑是首先根据输入的数字类型(整数、小数、分数、百分数)进行分类处理,然后对每个部分进行反转,最后输出反转后的数字。在处理小数和分数时,特别注意了前导零和末尾零的处理,以符合题目要求的数字表示形式。
踩到的坑
- 当我在处理末尾0时,我使用了
while (s.size() > 0 && s.back() == '0') s.pop_back();
,如果当该部分只有0时,例如0,0.123,0/56,0%,会把0删掉 - 小数部分的反转逻辑和其他部分略微不一样,例如0.056我一开始反转成了0.560,这是因为我在反转前先处理了末尾0,例如0.560先变为0.56,在反转为0.65,但这是错误的,0.056是正确的,所以我先反转,在处理末尾0