【id:287】【10分】G. OOP 罗马数字之加法(输入输出重载+类型转换)
时间限制
1s
内存限制
128MB
题目描述
罗马数字比阿拉伯数字早 2000 多年,起源于古罗马。它的产生标志着一种古代文明的进步。只是没有数字0。
其采用七个罗马字母作基本数字,即:I(1), V(5), X(10), L(50), C(100), D(500), M(1000)
记数的方法:
1. 相同的数字连写,所表示的数等于这些数字相加得到的数。如:III=3
2. 小数字在大数字的右边('大''小'),所表示的数等于这些数字相加得到的数。如:VIII=8
3. 小数字(仅限I,X和C)在大数字的左边('小''大'),所表示的数等于大数减小数得到的数。如:IX=9, CD=400
4. 在一个数的上面画一条横线,表示这个数增值1000倍。
组数规则:
I,X,C,M 连写或放在大数左边不能超过3个:LIIII是非法的,应表示为 LIV (54)
I,X,C 放在大数左边只能用1个:CCM是非法的,应表示为 MCCC (800)
V,L,D 放在大数的右边只能用1个:CLL是非法的,应直接表示为 CC (200)
V,L,D 不能放在大数的左边:DM是非法的,应直接表示为 D (500)
此外,表示2900,不能写成CMMM,而应写成MMCM (因为CM(90)比M(100)小)
表示900,不能写成DCD,而应写成CM (相比DCD,CM更简洁易算)
为避免打印横线,输入数据及运算结果范围保证为 [1,3999]
部分数字有两种写法,比如: 490(CDXC or XD) 3999(MMMCMXCIX or MMMIM) 等
本题采用较长的写法,即 CDXC(400+90) 等写法,而不是 XD(490) 写法
整数[1,3999]转罗马数字方法如下:
using value_t = unsigned short;
/// 表1: 490 = CDXC (本题使用该表)
static const pair<value_t, string> valueSymbols[] = {
{1000, "M"}, {900, "CM"},
{ 500, "D"}, {400, "CD"},
{ 100, "C"}, { 90, "XC"},
{ 50, "L"}, { 40, "XL"},
{ 10, "X"}, { 9, "IX"},
{ 5, "V"}, { 4, "IV"},
{ 1, "I"}
};
/// 表2: 490 = XD
//static const pair<value_t, string> valueSymbols[] = {
// {1000, "M"}, {999, "IM"}, {990, "XM"}, {900, "CM"},
// { 500, "D"}, {499, "ID"}, {490, "XD"}, {400, "CD"},
// { 100, "C"}, { 99, "IC"}, { 90, "XC"},
// { 50, "L"}, { 49, "IL"}, { 40, "XL"},
// { 10, "X"}, { 9, "IX"},
// { 5, "V"}, { 4, "IV"},
// { 1, "I"}
//};
/// 贪心, 处理罗马数字[1, 3999]
static string int2Roman(value_t num) {
string roman;
// for (const auto& [value, symbol] : valueSymbols) { // 8.1以上gcc编译器
// for (; num >= value; num -= value) {
// roman += symbol;
// }
// if (num == 0) break;
// }
for (int i=0; i<13; ++i) {
value_t value = valueSymbols[i].first;
string symbol = valueSymbols[i].second;
for (; num>=value; num-=value) {
roman += symbol;
}
}
return roman;
}
1. 要求实现一个RomanNumber类,在"不重载" operator+ 方法的情况下实现RomanNumber的加法
2. 为RomanNumber对象重载输入输出
主函数如下: (不可修改)
int main() {
int n;
cin >> n;
while (n--) {
RomanNumber ra, rb, rc;
cin>>ra>>rb;
rc = ra+rb;
cout << ra <<'+'<< rb <<'='<< rc <<'('<< ra+rb <<')'<<endl;
}
return 0;
}
输入
第1行: 1个正整数n,表示测试次数
以下n行: 每行两个正整数,用空格分隔
输出
(参见样例输出)
对于每个测试用例,输出运算表达式(使用罗马数字表示)
样例查看模式
正常显示
查看格式
输入样例1 <-复制
4
1 3
8 8
409 90
666 3333
输出样例1
I+III=IV(4)
VIII+VIII=XVI(16)
CDIX+XC=CDXCIX(499)
DCLXVI+MMMCCCXXXIII=MMMCMXCIX(3999)
这里使用到无符号short转换到构造函数的方法
在重写加法操作时,返回的不是类,而是一个无符号short。
这里需要注意的是,在运算后类赋值和运算后输出中,表面上看加法的作用不同
但是可以利用构造函数的多样性
输出的加法运算无法改变
在重载输入运算符>>时,需要传入的为一个指针,不是一个类变量。
在RomanNumber &romanNumber需要加&符号
friend istream &operator>>(istream &in, RomanNumber &romanNumber) {
in >> romanNumber.value;
return in;
}
在重载输出运算符<<时,&可加可不加
#include <iostream>
#include "map"
using namespace std;
class RomanNumber {
public:
unsigned short value;
using value_t = unsigned short;
/// 表1: 490 = CDXC (本题使用该表)
static pair<value_t, string> valueSymbols[];
RomanNumber(unsigned short value);
RomanNumber();
/// 表2: 490 = XD
//static const pair<value_t, string> valueSymbols[] = {
// {1000, "M"}, {999, "IM"}, {990, "XM"}, {900, "CM"},
// { 500, "D"}, {499, "ID"}, {490, "XD"}, {400, "CD"},
// { 100, "C"}, { 99, "IC"}, { 90, "XC"},
// { 50, "L"}, { 49, "IL"}, { 40, "XL"},
// { 10, "X"}, { 9, "IX"},
// { 5, "V"}, { 4, "IV"},
// { 1, "I"}
//};
/// 贪心, 处理罗马数字[1, 3999]
static string int2Roman(value_t num) {
string roman;
// for (const auto& [value, symbol] : valueSymbols) { // 8.1以上gcc编译器
// for (; num >= value; num -= value) {
// roman += symbol;
// }
// if (num == 0) break;
// }
for (int i = 0; i < 13; ++i) {
value_t value = valueSymbols[i].first;
string symbol = valueSymbols[i].second;
for (; num >= value; num -= value) {
roman += symbol;
}
}
return roman;
}
friend ostream &operator<<(ostream &out, RomanNumber romanNumber) {
out << int2Roman(romanNumber.value);
return out;
}
friend istream &operator>>(istream &in, RomanNumber &romanNumber) {
in >> romanNumber.value;
return in;
}
friend unsigned short operator+(RomanNumber one, RomanNumber two) {
RomanNumber res(one.value + two.value);
return one.value + two.value;
}
};
pair<unsigned short, string> RomanNumber::valueSymbols[] = {
{1000, "M"},
{900, "CM"},
{500, "D"},
{400, "CD"},
{100, "C"},
{90, "XC"},
{50, "L"},
{40, "XL"},
{10, "X"},
{9, "IX"},
{5, "V"},
{4, "IV"},
{1, "I"}
};
RomanNumber::RomanNumber(unsigned short value) : value(value) {}
RomanNumber::RomanNumber() {}
int main() {
int n;
cin >> n;
while (n--) {
RomanNumber ra, rb, rc;
cin >> ra >> rb;
rc = ra + rb;
// cout << ra.value << endl;
// cout << rb.value << endl;
// cout << rc.value << endl;
cout << ra << '+' << rb << '=' << rc << '(' << ra + rb << ')' << endl;
}
return 0;
}