#include #define FOR(i, a, b) for (int i = (a); i < (b); i++) #define RFOR(i, a, b) for (int i = (b)-1; i >= (a); i--) #define rep(i, n) for (int i = 0; i < (n); i++) #define rep1(i, n) for (int i = 1; i <= (n); i++) #define rrep(i, n) for (int i = (n)-1; i >= 0; i--) #define pb push_back #define mp make_pair #define fst first #define snd second #define show(x) cout << #x << " = " << x << endl #define chmin(x, y) x = min(x, y) #define chmax(x, y) x = max(x, y) #define pii pair #define vi vector using namespace std; template ostream& operator<<(ostream& o, const pair& p) { return o << "(" << p.first << "," << p.second << ")"; } template ostream& operator<<(ostream& o, const vector& vc) { o << "sz = " << vc.size() << endl << "["; for (const T& v : vc) o << v << ","; o << "]"; return o; } using ll = long long; constexpr ll MOD = 1000000007; struct RomanRadix { int digit; char roman; char romanNext; // Radix(int d, char r, char rn):digit(d),roman(r),romanNext(rn){} }; const int ROMAN_MAX_VALUE = 3999; const int ROMAN_MIN_VALUE = 1; const char RomanChars[] = "IVXLCDMivxlcdm"; class Roman { private: static bool isRomanString(const string& rstr) { return rstr.find_first_not_of(RomanChars) == string::npos; } static int rtoi_aux(const char ch) { static const char romans[] = "IVXLCDM"; static const int digit[] = {1, 5, 10, 50, 100, 500, 1000}; for (int i = 0; romans[i]; ++i) if (toupper(ch) == romans[i]) return digit[i]; return -1; } static int rtoi(const string& rstr) { int v, wk = 0; for (const char* p = rstr.c_str(); *p; ++p) { if ((v = rtoi_aux(*p)) < rtoi_aux(*(p + 1))) wk -= v; else wk += v; } return wk; } int num; string itor() const; public: Roman() : num(0) {} Roman(const int n); Roman(const string& r); int as_int() const { return num; } string as_str() const { return itor(); } friend Roman operator+(const Roman& a, const Roman& b) { int n = a.num + b.num; if (n > ROMAN_MAX_VALUE) throw std::overflow_error("overflow"); return Roman(n); } friend Roman operator-(const Roman& a, const Roman& b) { int n = a.num - b.num; if (n < ROMAN_MIN_VALUE) throw std::underflow_error("underflow"); return Roman(n); } }; Roman::Roman(const int n) : num(n) { if (num < 1 || 3999 < num) throw out_of_range("value need 1 - 3999"); }; Roman::Roman(const string& r) { if (!isRomanString(r)) throw invalid_argument("invalid character use"); num = rtoi(r); if (num < 1 || 3999 < num) throw out_of_range("value need 1 - 3999"); }; string Roman::itor() const { static RomanRadix table[] = { {1000, 'M', '?'}, {100, 'C', 'D'}, {10, 'X', 'L'}, {1, 'I', 'V'}}; const int tableSize = sizeof(table) / sizeof(RomanRadix); char buff[16]; //max size: 15 char* p = buff; for (int i = 0, wk = num; i < tableSize; ++i) { int n = wk / table[i].digit; if (1 <= n && n <= 3) { for (int j = 0; j < n; ++j) *p++ = table[i].roman; } else if (n == 4) { *p++ = table[i].roman; *p++ = table[i].romanNext; } else if (n == 5) { *p++ = table[i].romanNext; } else if (6 <= n && n <= 8) { *p++ = table[i].romanNext; for (int j = 0; j < n - 5; ++j) *p++ = table[i].roman; } else if (n == 9) { *p++ = table[i].roman; *p++ = table[i - 1].roman; } wk -= n * table[i].digit; } *p = '\0'; return string(buff); }; ostream& operator<<(ostream& os, const Roman& r) { return os << r.as_str(); } istream& operator>>(istream& is, Roman& r) { string rstr; is >> rstr; try { r = Roman(rstr); } catch (invalid_argument& e) { cerr << e.what() << endl; is.clear(ios_base::failbit); } return is; } std::ostream& operator<<(std::ostream& os, const Roman& r); std::istream& operator>>(std::istream& is, Roman& r); int main() { int N; cin >> N; int sum = 0; rep(i, N) { string str; cin >> str; Roman r(str); sum += r.as_int(); } if (sum >= 4000) { cout << "ERROR" << endl; return 0; } Roman r(sum); cout << r.as_str() << endl; return 0; }