結果
問題 | No.518 ローマ数字の和 |
ユーザー |
|
提出日時 | 2017-05-28 22:40:01 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 4,697 bytes |
コンパイル時間 | 1,479 ms |
コンパイル使用メモリ | 168,560 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-09-21 15:40:39 |
合計ジャッジ時間 | 2,182 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 19 |
ソースコード
#include <bits/stdc++.h>#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<int, int>#define vi vector<int>using namespace std;template <class S, class T>ostream& operator<<(ostream& o, const pair<S, T>& p){return o << "(" << p.first << "," << p.second << ")";}template <class T>ostream& operator<<(ostream& o, const vector<T>& 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;elsewk += 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: 15char* 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;}