#L3005. #3005. 「JOISC 2015 Day 4」Limited Memory

#3005. 「JOISC 2015 Day 4」Limited Memory

#3005. 「JOISC 2015 Day 4」Limited Memory


题目描述

译自 JOISC 2015 Day4 T2「Limited Memory」。

注意:在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:

  • C
  • C++
  • C++ (NOI)
  • C++ 11
  • C++ 11 (Clang)
  • C++ 11 (NOI)
  • C++ 17
  • C++ 17 (Clang)

JOI 酱被选为了日本代表去参加国际信息学奥林匹克竞赛。为了提高信息处理速度,日本国际信息学奥林匹克竞赛委员会的 K 理事长提出了一个课题。

K 理事长在纸上写下了一个字符串 SS,仅由 <>[] 组成,但是 JOI 酱不知道字符串具体是什么。JOI 酱会被告知字符串的长度,他的课题是判断字符串 SS 是不是一个合法字符串。合法字符串的定义如下:

  1. 空字符串(长度为 00 的字符串)是合法字符串。
  2. 假设 xx 是一个合法字符串,那么 <x> 也是合法字符串。
  3. 假设 xx 是一个合法字符串,那么 [x][x] 也是合法字符串。
  4. 假设 xxyy 都是合法字符串,那么 xyxy 也是合法字符串。

例如 <>[][<>]<> 都是合法字符串,而 ><[<]> 都不是合法字符串。

每天的中午,JOI 酱可以给 K 理事长打一个电话。电话里,JOI 酱可以指定一个整数 II,K 理事长会告诉他字符串 SS 的第 II 个字符。

现在 JOI 酱有一个限制:不能用其它东西记录这个课题相关的笔记。JOI 酱每天晚上 2222 点睡觉,早上 66 点起床。在睡眠中,她只能在脑中记下 2222 比特的信息。更准确的说,她会在睡前把一个 0022212^{22}-1 的整数记在脑内,然后第二天醒来根据这个整数来做决策。由于字符串长度是一开始就被告知的,JOI 酱是一直知道这个信息的。

JOI 酱每天睡前可以记住一个整数,或者发邮件告诉 K 理事长字符串 SS 是不是一个合法字符串。在后者的情况下,这个课题就结束了,K 理事长会判定你是否完成了这个课题。注意,邮件必须在课题开始后 1500015000 天内发给 K 理事长,不然你就算没有完成这个课题。


任务

请编写一个程序实现 JOI 酱的策略,并正确解出上述课题。


实现细节

你需要实现一个过程来确定字符串是否正确。请包含头文件 memory.h

程序需要实现以下过程。

int Memory(int N, int M)

  • 参数 NN 表示字符串 SS 的长度。
  • 参数 MM 表示上一天睡前记下的整数,在课题一开始的时候 M=0M = 0
  • 在这个函数里必须恰好调用一次 Get 函数。
  • 函数的返回值必须是一个 0022212^{22} - 1 的整数,或者 1-1,或者 2-2。如果返回值不在这些数里面,那么你的程序会被判为 Wrong Answer [1]
  • 返回值是 0022212^{22} - 1 的整数的话,表示这是睡前记下的数字。
  • 返回值是 1-1 的话,表示用邮件回答 SS 是一个合法字符串。
  • 返回值是 2-2 的话,表示用邮件回答 SS 不是一个合法字符串。
  • 这个函数应该理论上只依赖 NNMMGet 的返回值进行决策。在实际评测过程中这个函数会被调用 222×42^{22} \times 4 次,更详细的信息请参考「评分的顺序」。

此外,程序中可以调用如下函数。

char Get(int I)

  • 这个函数只能在调用 Memory 函数的时候被调用一次,如果调用了不止一次,你的程序会被判为 Wrong Answer [2]
  • 参数 II 是一个 11NN 的整数,不满足此条件时,会被判为 Wrong Answer [3]
  • 返回值是 SS 的第 II 个字符。

评分的顺序

每个测试文件会包含多组测试数据,每组测试数据对应的字符串 SS 的长度 NN 是一样的。评测过程如下,如果一旦被判定为了 Wrong Answer,你的程序会立刻被终止。

在给出参数 NNMMGet 的返回值的情况下,检查函数 Memory 的行为。也就是说对于满足 0M22210 \le M \le 2^{22} - 1 的整数 MM,做如下操作:

对于每个在 <>[] 的字符 cc,会执行如下操作:把 NNMM 作为参数传给 Memory 函数,当 Get 被调用的时候,把 cc 返回出去。用 m(M,c)m(M, c) 表示函数 Memory 的返回值。

上述操作会调用 44Memory 函数,需要检测 Get 的调用是否一致。如果 Get 被调用了,那么这 44 次传给 Get 的参数 II 必须一样。如果 Get 没有被调用,那么这 44Memory 的返回值必须要一样。不满足此条件时,会被判为 Wrong Answer [4]。当 Get 被调用的时候,我们令 i(M)i(M) 表示 II 的值(如果没有被调用 i(M)=1i(M)=1)。

对于每组数组里的字符串 SS,如下操作会被用来模拟课题描述

  1. 一开始 M=0M = 0
  2. 重复执行如下操作:
    • ccSS 的第 i(M)i(M) 个字符。
    • MM 换为 m(M,c)m(M, c)
    • M=1M = -1 或者 M=2M = -2 的情况下,跳出这个循环,进入下个流程。
  3. 如果循环了超过 1500015000 次,你的程序会被判为 Wrong Answer [5]
  4. 如果是以下某个情况,你的程序会被判为 Wrong Answer [6]
    • SS 是一个合法字符串,但是 M=2M = -2
    • SS 不是一个合法字符串,但是 M=1M = -1

你的程序被认为是正确的。


编译与运行方法

「附加文件」中提供了 memory.hgrader-simple.cgrader-simple.cppgrader-strict.cgrader-strict.cpp 五个文件。若你编写的程序名称为 memory.cmemory.cpp,请运行以下命令来编译:

C 语言

gcc -std=c11 -O2 -o grader-simple grader-simple.c memory.c -lm
gcc -std=c11 -O2 -o grader-strict grader-strict.c memory.c -lm

C++ 语言

g++ -std=c++14 -O2 -o grader-simple grader-simple.cpp memory.cpp
g++ -std=c++14 -O2 -o grader-strict grader-strict.cpp memory.cpp

当命令成功时,会产生一个可执行文件 grader-simple 或者 grader-strict

注意实际评测时的程序与下发的样例评测程序并不相同。实际的 memory.h 函数实现将通过标准输入/输出与单独运行的交互器进行交互。


样例程序评测概要

grader-simple 不会模拟「评分的顺序」的第一步,但是会模拟课题的操作,具体可以参考「样例交互」。grader-strict 会严格按照「评分的顺序」执行。两者在输出上会有如下的不同:

  • grader-simple 不会输出 Wrong Answer [4],因为它并没有模拟这个操作
  • grader-simplegrader-strict 不会输出 Wrong Answer [6],但是会输出 MM 的值。

样例评测程序输入格式

grader-simplegrader-strict 将从标准输入读入以下数据。

第一行包含两个整数 NNQQ (0Q2311)(0 \le Q \le 2^{31} - 1),表示字符串 SS 的长度和测试数据组数。

接下来 QQ 行,每行包含一个长度为 NN 的字符串 SS


样例评测程序输出格式

如果评测程序正常结束,grader-simplegrader-strict 将向标准输出输出以下信息。

  • 程序正常结束的话,会输出 MM 的值。
  • 运行过程中被判为错误时,以 Wrong Answer [x] 的格式报告并退出。

样例

样例评测输入

4 1
<>[]

样例交互

上述过程结束后 grader-simple 会输出 1-1


数据范围与提示

对于全部数据,满足 1S1001 \le |S| \le 100,字符串 SS 仅由 <>[] 组成。

本题共有 66 个子任务。每个子任务的分数和附加限制如下:

Subtask 附加限制 分数
1 SS 的长度不超过 88 1010
2 SS 的长度不超过 1414
3 SS 的长度不超过 2424 55
4 SS 的长度不超过 3030
5 字符串 SS 仅由 <> 组成 1010
6 无附加限制 6060