#include #include #include #include #include #include "validate.h" using namespace std; using i64 = long long; void read_integer(string name, i64 &x, i64 lo, i64 hi) { if (!(author_out >> x)) { wrong_answer("Wrong answer: expected an integer %s.\n", name.c_str()); } if (x < lo || x > hi) { wrong_answer("Wrong answer: %s = %lld, but must be in range [%lld,%lld].\n", name.c_str(), x, lo, hi); } } const string digits = "MDCLXVI"; void check_roman(string num) { transform(begin(num), end(num), begin(num), [](char c) { return toupper(c); }); for (char c: num) { if (digits.find(c) == string::npos) { wrong_answer("Wrong answer: invalid character in Roman numeral: '%c'.\n", isprint(c) ? c : '?'); } } regex roman_regex("M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})"); if (num.empty() || !regex_match(num, roman_regex)) { wrong_answer("Wrong answer: not a valid Roman numeral: %s.\n", num.c_str()); } } const i64 B = 2e18; // upper bound for summations that might overflow otherwise string to_string_with_bound(i64 n) { return n >= B ? "at least " + to_string(B) : to_string(n); } int main(int argc, char **argv) { init_io(argc,argv); map supply; for (char c: digits) judge_in >> supply[c]; i64 ans; read_integer("n", ans, 1, 1e18); // Don't compare the answer right away so we can give more informative feedback later. i64 k; read_integer("k", k, 1, 3999); i64 sum = 0; map used; set numerals; for (int i = 0; i < k; i++) { string num; if (!(author_out >> num)) { wrong_answer("Wrong answer: expected a Roman numeral.\n"); } check_roman(num); if (numerals.count(num)) { wrong_answer("Wrong answer: output contains a duplicate Roman numeral.\n"); } numerals.insert(num); i64 m; read_integer("m", m, 1, 1e18); sum = min(sum + m, B); for (char c: num) { used[c] = min(used[c] + m, B); } } string junk; if (author_out >> junk) { wrong_answer("Wrong answer: found trailing output.\n"); } if (sum != ans) { wrong_answer("Wrong answer: solution consists of %s numerals, but author claimed %lld.\n", to_string_with_bound(sum).c_str(), ans); } for (char c: digits) { if (used[c] != supply[c]) { wrong_answer("Wrong answer: should use %lld of digit %c, but actually used %s.\n", supply[c], c, to_string_with_bound(used[c]).c_str()); } } i64 res; judge_ans >> res; if (ans > res) { wrong_answer("Wrong answer: solution not optimal.\n"); } else if (ans < res) { judge_error("Judge error: author found better solution than judge!\n"); } accept(); }