虽然在算法竞赛中不常用,但是面向对象确实是 c++ 编程中非常重要的一部分。
在北京大学信科的培养方案中,面向对象编程是每一名本科生的必修课。今天,蒜斜在整理他以前的课程资料的时候,找到了他学习面向对象编程时的大作业代码。然而,因为一些未知的原因,代码里的一些内容丢失了。
于是蒜斜找到了你,希望你能帮他复原一下这个代码。复原的方式有很多,于是他希望你能告诉他不同的复原方式有多少种。
问题描述
给出一个损坏的 c++ 代码。因为数据丢失的原因,这个代码里存在一些未知的空缺。空缺有两类:
- 修饰符空缺,用
/*MissingModifier*/
表示。在原本程序中,这一类空缺对应的一定是标识符private
,protected
和public
中的一个。 - 函数空缺,用
/*MissingMethod*/
表示。在原本程序中,这一类空缺对应的一定是一个形如method#Num
的函数名,其中#Num
对应了一个正整数。
给定一个损坏的 c++ 代码,你需要计算有多少种填写空缺的方案,使得填写后的程序是可以正常通过编译的。这个方案数可能会很大,因此你只需要输出方案数对 $998244353$ 取模后的结果。
例子
下面给出了一个损坏的 c++ 代码。
class Class1 {
void method1() {
/*MissingMethod*/();
}
/*MissingModifier*/:
void method2() {}
};
class Class2: /*MissingModifier*/ Class1 {
/*MissingModifier*/:
void method3() {}
/*MissingModifier*/:
void method4() {}
};
int main() {
Class2 o2;
o2./*MissingMethod*/();
}
我们按照从上到下的顺序依次把 /*MissingModifier*/
命名为 $x_1, x_2,x_3,x_4$,把 /*MissingMethod*/
命名为 $y_1,y_2$。不难发现 $y_1$ 的填法和其他空缺的填法无关,它始终可以取 method1
或者 method2
。因此我们可以先忽略这个空缺,然后在最后把答案乘以 $2$。
对 $y_2$ 的取值分类讨论:
method1
。这时一定无法编译通过,因为method1
是Class1
的私有函数。method2
。因为是通过O2
调用的method2
,所以可以得到 $x_1,x_2$ 一定都是public
。此时对 $x_3,x_4$ 的填法没有要求,因此方案数为 $9$。method3
。可以得到 $x_3$ 一定是public
。此时对 $x_1,x_2,x_4$ 的填法没有要求,因此方案数为 $27$。method4
。与method3
同理,可以得到方案数为 $27$。
因此,总的方案数为 $(9+27+27) \times 2 = 126$。
限制与约定
本题的两个部分各给出了一个部分程序(见下发文件下载),分别为 oo1.in
和 oo2.in
。对于每一个部分,你只需要提交一个数字,表示对应部分程序的答案。
为了节约大家的时间,这儿给出输入程序的一部分性质:
- 保证存在一种填写空缺的方法可以使得输入程序能够通过编译。
- 输入程序中除了主函数
main
以外,所有的函数均为成员函数。 - 输入程序中没有使用虚函数和静态函数。
- 输入程序中所有的修饰符
public
,protected
和private
均被替换为了空缺/*MissingModifier*/
。 - 输入程序中所有的函数调用均被替换为了空缺
/*MissingMethod*/
,所有函数声明中的函数名均没有被替换。 - 输入程序中所有类按照出现顺序依次命名为
Class1
,Class2
等等。所有成员函数按照出现顺序依次命名为method1
,method2
等等。 - 除了
Class1
以外,其他所有类均有一个父类。 - 所有类均不包含任何成员变量。
- 输入程序中类的数量不超过 $300$ 个,成员函数总数以及函数调用总数不超过 $1000$ 个。
在 small task 中,输入程序 oo1.in
还保证:
- 主函数
main
为空。 - 在每一个成员函数的声明之前,均有一个修饰符空缺
/*MissingModifier*/:
。