浅谈online judge平台 spj [special judge] 使用 | 修改问题(上)

简介: 浅谈oj平台 spj 使用 | 修改问题首先:参数对应返回值代码提交几种spj第一种:简单的一类特判第二种:多组输入的特判第三种:需要判断特殊情况[impossible]第四种:带有[testlib.h]的spj第五种:GCPC [German Collegiate Programming Contest] 类spj

浅谈oj平台 spj 使用 | 修改问题


以LDUOJ为例 goto -> github

LDUOJ 平台开发者spj开发博客


不同的平台的spj使用规则可能不太一样,但是需要改动的地方不是太多


首先:


参数对应


args[1] 对应数据的输入

args[2] 对应数据的答案也就是一种允许的情况 或 impossible的情况(下面会讲到)

args[3] 对应用户结果的输出,也就是需要重点关注的地方


返回值


0代表没有问题即 AC

1代表出现问题即 WA

对于有的系统来说

42代表AC,43代表WA,不同的系统可能是不一样的返回值


代码提交


和牛客平台等类似,提交的Java代码主类的类名必须是Main否则会编译错误

就比如应该是:

public class Main{
  public static void main(){
    /**
    your code
    **/
  }
}


几种spj


第一种:简单的一类特判


比如下面这个比较简单的spj程序:

#include <stdio.h>
#include <math.h>
#include <cstring>
const double eps = 1e-6;
int main(int argc,char *args[])
{
    FILE * f_in=fopen(args[1],"r");
    FILE * f_out=fopen(args[2],"r");
    FILE * f_user=fopen(args[3],"r");
    fclose(f_in);
    fclose(f_out);
    fclose(f_user);
    return ret;
}


用文件指针的情况,我们可以直接用fscanf 进行输入输出

格式如下:


fscanf(pnt,"%d",&x);


其中pnt为想要从哪里读取的文件指针。比如要获取用户的输出,就要将pnt替换为f_user


第二种:多组输入的特判


示例:UVA10886

ec5c1a04706344ff9a8bb4742d189d8f.png


对应的spj程序应该是:

#include <stdio.h>
#include <math.h>
const double eps = 1e-4;
int main(int argc,char *args[])///主函数
{
    FILE * f_in=fopen(args[1],"r");///测试输入
    FILE * f_out=fopen(args[2],"r");///测试输出
    FILE * f_user=fopen(args[3],"r");///用户输出
    int ret=0;///返回值
    int T;
    double a,x;
    char cas[100],num[100];
    fscanf(f_in,"%d",&T);///从输入中读取数据组数T
    while(T--)
    {
        fscanf(f_out,"%s %s %lf",&cas,&num,&a);
        fscanf(f_user,"%s %s %lf",&cas,&num,&x);
        if(fabs(a-x)>eps)
            ret = 1;///Wrong Answer
    }
    fclose(f_in);
    fclose(f_out);
    fclose(f_user);
    return ret;
}


第三种:需要判断特殊情况[impossible]


903418d95fe34d2c8005add7ae3d4a3f.png

则对应的spj就应该为:

#include <stdio.h>
#include <math.h>
#include <cstring>
const double eps = 1e-6;
int main(int argc,char *args[])
{
    FILE * f_in=fopen(args[1],"r");
    FILE * f_out=fopen(args[2],"r");
    FILE * f_user=fopen(args[3],"r");
    int ret = 0;
    double a,x;
    char std[100],usr[100];
    while(fscanf(f_out,"%s",std) == 1 && fscanf(f_user,"%s",usr) == 1){
      if(strcmp(std,"IMPOSSIBLE") && !strcmp(usr,"IMPOSSIBLE")) 
    {
      ret = 1;
      return ret;
    }
    if(strcmp(usr,"IMPOSSIBLE") && !strcmp(std,"IMPOSSIBLE"))
    {
      ret = 1;
      return ret;
    }
    double sstd = atof(std);
    double uusr = atof(usr);
    if(fabs(sstd - uusr) > eps) {
      ret = 1;
      return ret;
    }
  }
    fclose(f_in);
    fclose(f_out);
    fclose(f_user);
    return ret;
}


第四种:带有[testlib.h]的spj


一般情况下,这种题目的spj都是比较规范的,而且testlib.h是在Github上进行开源的

该头文件的发明者应该是Codeforces的管理员 MikeMirzayanov

只需要将上述中的args[]对应好就没有太大问题

2021-09-16更新

在处理的过程当中,笔者发现大部分的testlib.h类的spj与lduoj是匹配的

所以说在处理的时候如果发现spj编译报错,那么就说明用到的checker.cpp和testlib.h的版本不对应,应该参考附带的testlib.h,然后拼接在一起


daeea26367664da29266239328425c50.png

如果发现更改spj之后还不通过std代码,首先可以试试所有的语言的标程,如果还是不通过,可以确定是spj的问题,这里就需要对spj统一换成比较朴实的spj,具体什么格式可以参考文章首部的oj开发者提供的spj使用规范

需要重新实现一下使用到的testlib.h里面的函数方法即可


第五种:GCPC [German Collegiate Programming Contest] 类spj


单个文件的情况


这种情况比较简单

以GCPC2019 Keeping the Dogs Out为例:

0a3768b7535c4385926fc61662051ff8.png


打开可以看到:

#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
#include <cassert>
typedef long long ll;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
using std::vector;
constexpr int CORRECT = 42;///修改
constexpr int INCORRECT = 43;///修改
int main(int argc, char* argv[])
{
    assert(argc == 4);
    ifstream input(argv[1]);
    ifstream answer(argv[2]);
    ofstream debug_output(argv[3] + string("/judgemessage.txt"));///修改
    string s1, s2;
    answer >> s1;
    cin >> s2;
    if (s1 != s2 && (s1 == "impossible" || s2 == "impossible")) {
        debug_output << "Expected: " << s1 << ", got: " << s2 << endl;///被迫对应修改
        return INCORRECT;
    }
    if (s1 != "impossible") {
        ll x, y;
        std::stringstream first_token(s2);
        if (!(first_token >> x) || !(cin >> y)) {
            debug_output << "Too little output" << endl;///被迫对应修改
            return INCORRECT;
        }
        if (!cin || x <= 0 || y <= 0) {
            debug_output << "Presentation Error" << endl;///被迫对应修改
            return INCORRECT;
        }
        if (std::numeric_limits<ll>::max() / x < y) {
            debug_output << "Area too large." << endl;///被迫对应修改
            return INCORRECT;
        }
        ll n;
        input >> n;
        vector<ll> cnt(n + 1);
        for (ll& i: cnt) input >> i;
        ll current_area = 0;
        for (int k = n; k >= 0; --k) {
            ll border_length = 1ll << k;
            current_area += border_length * border_length * cnt[k];
            ll a = (x / border_length) * border_length;
            ll b = (y / border_length) * border_length;
            if (a * b < current_area) {
                debug_output << "Incorrect dimensions, cannot fit all squares of size " << border_length << " and larger." << endl;///被迫对应修改
                return INCORRECT;
            }
        }
        if (current_area != x * y) {
            debug_output << "Area is " << x * y << ", should be " << current_area << "." << endl;///被迫对应修改
            return INCORRECT;
        }
    }
    char c;
    if (cin >> c) {
        debug_output << "Too much output." << endl;///被迫对应修改
        return INCORRECT;
    }
    return CORRECT;
}


改过之后的spj应该是这样子的:

值得一提的是,这里的输入并不是通过文件指针,而是通过流的方式读写文件

而且GCPC比赛平台的argc[3] 应该是将结果反馈给平台的一个参数


#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
#include <cassert>
typedef long long ll;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
using std::vector;
constexpr int CORRECT = 0;
constexpr int INCORRECT = 1;
int main(int argc, char* argv[])
{
//    assert(argc == 4);
    ifstream input(argv[1]);
    ifstream answer(argv[2]);
    ifstream user(argv[3]);
//    ofstream debug_output(argv[3] + string("/judgemessage.txt"));
    string s1, s2;
    answer >> s1;
    user >> s2;
    if (s1 != s2 && (s1 == "impossible" || s2 == "impossible")) {
        return INCORRECT;
    }
    if (s1 != "impossible") {
        ll x, y;
        std::stringstream first_token(s2);
        if (!(first_token >> x) || !(user >> y)) {
            return INCORRECT;
        }
        if (!user || x <= 0 || y <= 0) {
            return INCORRECT;
        }
        if (std::numeric_limits<ll>::max() / x < y) {
            return INCORRECT;
        }
        ll n;
        input >> n;
        vector<ll> cnt(n + 1);
        for (ll& i: cnt) input >> i;
        ll current_area = 0;
        for (int k = n; k >= 0; --k) {
            ll border_length = 1ll << k;
            current_area += border_length * border_length * cnt[k];
            ll a = (x / border_length) * border_length;
            ll b = (y / border_length) * border_length;
            if (a * b < current_area) {
                return INCORRECT;
            }
        }
        if (current_area != x * y) {
            return INCORRECT;
        }
    }
    char c;
    if (user >> c) {
        return INCORRECT;
    }
    return CORRECT;
}


*.h *.cpp的情况


以GCPC 2019 Historical Maths为例:

5c42bb7c0c2c43329652a95ca7378160.png


我们只需要将两个文件合并在一起就好.h文件放在上面,.cpp文件放在下面

如果遇见了某结构体或者是类里面的某个共有或私有函数没有生命的情况,八成加上using namespace std 可以解决

以这个题为例,合并这些文件之后的spj为:


#include <bits/stdc++.h>
/* Utility functions for writing output validators for the Kattis
 * problem format.
 *
 * The primary functions and variables available are the following.
 * In many cases, the only functions needed are "init_io",
 * "wrong_answer", and "accept".
 *
 * - init_io(argc, argv):
 *        initialization
 *
 * - judge_in, judge_ans, author_out:
 *        std::istream objects for judge input file, judge answer
 *        file, and submission output file.
 *
 * - accept():
 *        exit and give Accepted!
 *
 * - accept_with_score(double score):
 *        exit with Accepted and give a score (for scoring problems)
 *
 * - judge_message(std::string msg, ...):
 *        printf-style function for emitting a judge message (a
 *        message that gets displayed to a privileged user with access
 *        to secret data etc).
 *
 * - wrong_answer(std::string msg, ...):
 *        printf-style function for exitting and giving Wrong Answer,
 *        and emitting a judge message (which would typically explain
 *        the cause of the Wrong Answer)
 *
 * - judge_error(std::string msg, ...):
 *        printf-style function for exitting and giving Judge Error,
 *        and emitting a judge message (which would typically explain
 *        the cause of the Judge Error)
 *
 * - author_message(std::string msg, ...):
 *        printf-style function for emitting an author message (a
 *        message that gets displayed to the author of the
 *        submission).  (Use with caution, and be careful not to let
 *        it leak information!)
 *
 */
#include <sys/stat.h>
#include <cassert>
#include <cstdarg>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
typedef void (*feedback_function)(const std::string &, ...);
const int EXITCODE_AC = 42;///注释 / 修改
const int EXITCODE_WA = 43;///注释 / 修改
const std::string FILENAME_AUTHOR_MESSAGE = "teammessage.txt";
const std::string FILENAME_JUDGE_MESSAGE = "judgemessage.txt";
const std::string FILENAME_JUDGE_ERROR = "judgeerror.txt";
const std::string FILENAME_SCORE = "score.txt";
#define USAGE "%s: judge_in judge_ans feedback_dir < author_out\n"
std::ifstream judge_in, judge_ans;
std::istream author_out(std::cin.rdbuf());///修改
char *feedbackdir = NULL;
void vreport_feedback(const std::string &category,
    const std::string &msg,
    va_list pvar) {
  std::ostringstream fname;
  if (feedbackdir)
    fname << feedbackdir << '/';
  fname << category;
  FILE *f = fopen(fname.str().c_str(), "a");
  assert(f);
  vfprintf(f, msg.c_str(), pvar);
  fclose(f);
}
void report_feedback(const std::string &category, const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(category, msg, pvar);
}
void author_message(const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(FILENAME_AUTHOR_MESSAGE, msg, pvar);
}
void judge_message(const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar);
}
void wrong_answer(const std::string &msg, ...) {
  va_list pvar;///注释 / 修改
  va_start(pvar, msg);
  vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar);
  exit(EXITCODE_WA);
}
void judge_error(const std::string &msg, ...) {
  va_list pvar;///注释 / 修改
  va_start(pvar, msg);
  vreport_feedback(FILENAME_JUDGE_ERROR, msg, pvar);
  assert(0);
}
void accept() {
  exit(EXITCODE_AC);
}
void accept_with_score(double scorevalue) {
  report_feedback(FILENAME_SCORE, "%.9le", scorevalue);
  exit(EXITCODE_AC);
}
bool is_directory(const char *path) {
  struct stat entry;
  return stat(path, &entry) == 0 && S_ISDIR(entry.st_mode);
}
void init_io(int argc, char **argv) {
  if(argc < 4) {///注释 / 修改
    fprintf(stderr, USAGE, argv[0]);///注释 / 修改
    judge_error("Usage: %s judgein judgeans feedbackdir [opts] < userout", argv[0]);///注释 / 修改
  }///注释 / 修改
///注释 / 修改
  // Set up feedbackdir first, as that allows us to produce feedback///注释 / 修改
  // files for errors in the other parameters.///注释 / 修改
  if (!is_directory(argv[3])) {///注释 / 修改
    judge_error("%s: %s is not a directory\n", argv[0], argv[3]);///注释 / 修改
  }///注释 / 修改
  feedbackdir = argv[3];///注释 / 修改
  judge_in.open(argv[1], std::ios_base::in);
  if (judge_in.fail()) {
    judge_error("%s: failed to open %s\n", argv[0], argv[1]);
  }
  judge_ans.open(argv[2], std::ios_base::in);
  if (judge_ans.fail()) {
    judge_error("%s: failed to open %s\n", argv[0], argv[2]);
  }
  author_out.rdbuf(std::cin.rdbuf());///注释 / 修改
}
using namespace std;
using ll = long long;
using vl = vector<ll>;
#define sz(c) ll((c).size())
#define FOR(i,a,b) for(ll i = (a); i < (b); i++)
#define FORD(i,a,b) for(ll i = ll(b) - 1; i >= (a); i--)
const ll MAX_BASE = (2LL << 60) + 1;
ll check_and_parse_author(const string& to_parse) {
  //first pass; check for invalid character
  if(sz(to_parse) == 0) wrong_answer("Submission provided empty string to parse.\n");
  if(to_parse[0] == '+' && sz(to_parse) == 1) wrong_answer("Answer is not a number.\n");
  if(to_parse[0] != '+' && (to_parse[0] < '0' || '9' < to_parse[0])) wrong_answer("Answer contains invalid character.\n");
  FOR(i,1,sz(to_parse)) if(to_parse[i] < '0' || '9' < to_parse[i]) wrong_answer("Answer contains invalid character.\n");
  //second pass; calculate answer base
  ll base = 0;
  if(to_parse[0] != '+') base = to_parse[0] - '0';
  FOR(i,1,sz(to_parse)) {
    // avoid overflow
    if(MAX_BASE / 10 < base) return MAX_BASE;
    base = base*10 + (to_parse[i] - '0');
  }
  return base;
}
void multiply(vl &a, vl &b, vl &res, ll base) {
  res.assign(sz(res), 0);
  FOR(i,0,sz(a)) {
    FOR(j,0,sz(b)) {
      res[i + j] += a[i] * b[j];
      res[i + j + 1] += res[i + j] / base;
      res[i + j] %= base;
    }
  }
  FOR(i,0,sz(res) - 1) {
    res[i + 1] += res[i] / base;
    res[i] %= base;
  }
}
ll compare(vl &a, vl &b) {
  if(sz(a) < sz(b)) {
    FOR(i,sz(a),sz(b)) if(b[i] != 0) return -1;
  }
  if(sz(a) > sz(b)) {
    FOR(i,sz(b), sz(a)) if(a[i] != 0) return 1;
  }
  FORD(i,0,min(sz(a),sz(b))) {
    if(a[i] - b[i] != 0) return a[i] - b[i];
  }
  return 0;
}
int main(int argc, char **argv) {
  init_io(argc,argv);///注释 / 修改这个函数
  string a_ans, j_ans;
  char foo;
  judge_ans >> j_ans;
  if(!( author_out >> a_ans)) wrong_answer("Less output than expected.\n");
  if(author_out >> foo) wrong_answer("More output than expected.\n");
  transform(a_ans.begin(), a_ans.end(), a_ans.begin(), ::tolower);
  //quick accept
  if(a_ans == j_ans) accept();
  if(a_ans == "impossible") wrong_answer("Submission claims impossible, judge has answer.\n");
  ll base = check_and_parse_author(a_ans);
  if(base < 2) wrong_answer("Invalid base.\n");
  bool differs = false;
  if(j_ans == "impossible") differs = true;
  ll tmp, maxdigit = 1;
  judge_in >> tmp;
  vl a(tmp);
  FORD(i, 0, tmp) {judge_in >> a[i]; maxdigit = max(maxdigit, a[i]);}
  judge_in >> tmp;
  vl b(tmp);
  FORD(i, 0, tmp){ judge_in >> b[i]; maxdigit = max(maxdigit, b[i]);}
  judge_in >> tmp;
  vl prod(tmp);
  FORD(i, 0, tmp){ judge_in >> prod[i]; maxdigit = max(maxdigit, prod[i]);}
  vl res(sz(a) + sz(b) + 1);
  if(base < maxdigit + 1) wrong_answer("Base not greater than all occuring digits.\n");
  multiply(a,b,res,base);
  ll cmp = compare(prod, res);
  if(cmp == 0) {
    if(differs)
      judge_error("Judge answer is 'impossible' but submission gave valid answer.\n");
    accept();
  }
  wrong_answer("Invalid base.\n");
}


由于平台不同的原因,在函数含有某行对文件写操作的代码会出现问题,所以要注释掉,还要将返回的状态码改成0 1,而不是使用42 43

注意有些头文件在Windows平台下并不能使用,会报出编译错误,但是在Linux平台下却是可以的,提交spj之后会编译成功

需要修改的地方已在上面的代码中加入了批注,然后,修改之后应该是:


#include <bits/stdc++.h>
#include <sys/stat.h>
#include <cassert>
#include <cstdarg>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
typedef void (*feedback_function)(const std::string &, ...);
const int EXITCODE_AC = 0;
const int EXITCODE_WA = 1;
const std::string FILENAME_AUTHOR_MESSAGE = "teammessage.txt";
const std::string FILENAME_JUDGE_MESSAGE = "judgemessage.txt";
const std::string FILENAME_JUDGE_ERROR = "judgeerror.txt";
const std::string FILENAME_SCORE = "score.txt";
#define USAGE "%s: judge_in judge_ans feedback_dir < author_out\n"
std::ifstream judge_in, judge_ans;
std::ifstream author_out;
char *feedbackdir = NULL;
void vreport_feedback(const std::string &category,
                      const std::string &msg,
                      va_list pvar) {
  std::ostringstream fname;
  if (feedbackdir)
    fname << feedbackdir << '/';
  fname << category;
  FILE *f = fopen(fname.str().c_str(), "a");
  assert(f);
  vfprintf(f, msg.c_str(), pvar);
  fclose(f);
}
void report_feedback(const std::string &category, const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(category, msg, pvar);
}
void author_message(const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(FILENAME_AUTHOR_MESSAGE, msg, pvar);
}
void judge_message(const std::string &msg, ...) {
  va_list pvar;
  va_start(pvar, msg);
  vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar);
}
void wrong_answer(const std::string &msg, ...) {
//  va_list pvar;
//  va_start(pvar, msg);
//  vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar);
  exit(EXITCODE_WA);
}
void judge_error(const std::string &msg, ...) {
//  va_list pvar;
//  va_start(pvar, msg);
//  vreport_feedback(FILENAME_JUDGE_ERROR, msg, pvar);
  assert(0);
}
void accept() {
  exit(EXITCODE_AC);
}
void accept_with_score(double scorevalue) {
//  report_feedback(FILENAME_SCORE, "%.9le", scorevalue);
  exit(EXITCODE_AC);
}
bool is_directory(const char *path) {
  struct stat entry;
  return stat(path, &entry) == 0 && S_ISDIR(entry.st_mode);
}
void init_io(int argc, char **argv) {
//  if(argc < 4) {
//    fprintf(stderr, USAGE, argv[0]);
//    judge_error("Usage: %s judgein judgeans feedbackdir [opts] < userout", argv[0]);
//  }
//
//  // Set up feedbackdir first, as that allows us to produce feedback
//  // files for errors in the other parameters.
//  if (!is_directory(argv[3])) {
//    judge_error("%s: %s is not a directory\n", argv[0], argv[3]);
//  }
//  feedbackdir = argv[3];
  judge_in.open(argv[1], std::ios_base::in);
  if (judge_in.fail()) {
    judge_error("%s: failed to open %s\n", argv[0], argv[1]);
  }
  judge_ans.open(argv[2], std::ios_base::in);
  if (judge_ans.fail()) {
    judge_error("%s: failed to open %s\n", argv[0], argv[2]);
  }
  author_out.open(argv[3], std::ios_base::in);
  if (author_out.fail()) {
    judge_error("%s: failed to open %s\n", argv[0], argv[3]);
  }
}
using namespace std;
using ll = long long;
using vl = vector<ll>;
#define sz(c) ll((c).size())
#define FOR(i,a,b) for(ll i = (a); i < (b); i++)
#define FORD(i,a,b) for(ll i = ll(b) - 1; i >= (a); i--)
const ll MAX_BASE = (2LL << 60) + 1;
ll check_and_parse_author(const string& to_parse) {
  //first pass; check for invalid character
  if(sz(to_parse) == 0) wrong_answer("Submission provided empty string to parse.\n");
  if(to_parse[0] == '+' && sz(to_parse) == 1) wrong_answer("Answer is not a number.\n");
  if(to_parse[0] != '+' && (to_parse[0] < '0' || '9' < to_parse[0])) wrong_answer("Answer contains invalid character.\n");
  FOR(i,1,sz(to_parse)) if(to_parse[i] < '0' || '9' < to_parse[i]) wrong_answer("Answer contains invalid character.\n");
  //second pass; calculate answer base
  ll base = 0;
  if(to_parse[0] != '+') base = to_parse[0] - '0';
  FOR(i,1,sz(to_parse)) {
    // avoid overflow
    if(MAX_BASE / 10 < base) return MAX_BASE;
    base = base*10 + (to_parse[i] - '0');
  }
  return base;
}
void multiply(vl &a, vl &b, vl &res, ll base) {
  res.assign(sz(res), 0);
  FOR(i,0,sz(a)) {
    FOR(j,0,sz(b)) {
      res[i + j] += a[i] * b[j];
      res[i + j + 1] += res[i + j] / base;
      res[i + j] %= base;
    }
  }
  FOR(i,0,sz(res) - 1) {
    res[i + 1] += res[i] / base;
    res[i] %= base;
  }
}
ll compare(vl &a, vl &b) {
  if(sz(a) < sz(b)) {
    FOR(i,sz(a),sz(b)) if(b[i] != 0) return -1;
  }
  if(sz(a) > sz(b)) {
    FOR(i,sz(b), sz(a)) if(a[i] != 0) return 1;
  }
  FORD(i,0,min(sz(a),sz(b))) {
    if(a[i] - b[i] != 0) return a[i] - b[i];
  }
  return 0;
}
int main(int argc, char **argv) {
  init_io(argc,argv);
  string a_ans, j_ans;
  char foo;
  judge_ans >> j_ans;
  if(!( author_out >> a_ans)) wrong_answer("Less output than expected.\n");
  if(author_out >> foo) wrong_answer("More output than expected.\n");
  transform(a_ans.begin(), a_ans.end(), a_ans.begin(), ::tolower);
  //quick accept
  if(a_ans == j_ans) accept();
  if(a_ans == "impossible") wrong_answer("Submission claims impossible, judge has answer.\n");
  ll base = check_and_parse_author(a_ans);
  if(base < 2) wrong_answer("Invalid base.\n");
  bool differs = false;
  if(j_ans == "impossible") differs = true;
  ll tmp, maxdigit = 1;
  judge_in >> tmp;
  vl a(tmp);
  FORD(i, 0, tmp) {
    judge_in >> a[i];
    maxdigit = max(maxdigit, a[i]);
  }
  judge_in >> tmp;
  vl b(tmp);
  FORD(i, 0, tmp) {
    judge_in >> b[i];
    maxdigit = max(maxdigit, b[i]);
  }
  judge_in >> tmp;
  vl prod(tmp);
  FORD(i, 0, tmp) {
    judge_in >> prod[i];
    maxdigit = max(maxdigit, prod[i]);
  }
  vl res(sz(a) + sz(b) + 1);
  if(base < maxdigit + 1) wrong_answer("Base not greater than all occuring digits.\n");
  multiply(a,b,res,base);
  ll cmp = compare(prod, res);
  if(cmp == 0) {
    if(differs)
      judge_error("Judge answer is 'impossible' but submission gave valid answer.\n");
    accept();
  }
  wrong_answer("Invalid base.\n");
}



目录
相关文章
|
Python
【hacker的错误集】TypeError: can‘t multiply sequence by non-int of type ‘str‘
我比较喜欢通过单词的意思来分析报错 TypeError类型错误 multiply乘 sequence 序列 通过分析可以得出报错意思大概是类型错误:无法将序列与字符串类型的非整数相乘
315 0
【hacker的错误集】TypeError: can‘t multiply sequence by non-int of type ‘str‘
浅谈online judge平台 spj [special judge] 使用 | 修改问题(下)
第六种:交互题的spj 第七种[带有testlib.h]的另一种解决方式 第八种 使用validation.h的BAPC2018(较难)
446 0
PAT (Advanced Level) Practice - 1068 Find More Coins(30 分)
PAT (Advanced Level) Practice - 1068 Find More Coins(30 分)
92 0
|
C++
PAT (Advanced Level) Practice - 1038 Recover the Smallest Number(30 分)
PAT (Advanced Level) Practice - 1038 Recover the Smallest Number(30 分)
99 0
|
Android开发
AVD Pixel_2_API_30 is already running. lf that is not the case, delete the files at
AVD Pixel_2_API_30 is already running. lf that is not the case, delete the files at
794 0
AVD Pixel_2_API_30 is already running. lf that is not the case, delete the files at
HDOJ 1095 A+B for Input-Output Practice (VII)
HDOJ 1095 A+B for Input-Output Practice (VII)
79 0
HDOJ 1096 A+B for Input-Output Practice (VIII)
HDOJ 1096 A+B for Input-Output Practice (VIII)
78 0
SAP PM 入门系列18 - IP25为维护计划 Set Deletion Flag
SAP PM 入门系列18 - IP25为维护计划 Set Deletion Flag
SAP PM 入门系列18 - IP25为维护计划 Set Deletion Flag