LCR 最近发明了一种新的编程语言 A++。然而令她始料未及的是,小明刚刚学会循环就开始祸害全国 OIer。LCR 决定教他做人,于是写了一些程序要小明计算渐进时间复杂度。
由于小明利用 A++ 参与的 NOI 系列赛事将常数优化作为一大考点,LCR 还要求小明计算出这些程序的渐进常数因子。
A++ 语言有语句、正整数常数,正整数型变量、For 循环和一元函数这几种语法。
一份 A++ 源代码只包含以下字符:
* 可见字符,包括大小写拉丁字母 A~Z 和 a~z,数字 0~9。
* 空白字符,包括半角空格,换行 \n,回车 \r,制表 \t。
我们定义一个词是一段长度达到极大的由可见字符组成的连续段。
A++ 的基本单位是语句,其按换行 \n 分隔,每行开头一个词表示语句类型:
* Func 表示这是个函数的开头
* F 表示这是个 For 循环的开头
* E 表示这是某个函数或 For 循环的结束
* <函数名> 表示调用该函数
* S 表示时间复杂度标志语句
词 Func,F,E,S 称为关键字。
每种语句完整的语法格式如下:
* Func <函数名> 表示声明一个一元函数 <函数名>。调用函数时,一个名为 n 的变量建立,作用域开始,表示传入函数的参数。
函数名是一个以大写字母开头的词,不同函数不重名,函数不与关键字重名,该函数结束之前的语句不能调用该函数(即,先声明的函数不能调用后声明的函数,也不允许递归调用)。
* F <变量名> <起始> <终止> 表示变量 <变量名>的建立,作用域开始并初始化为 <起始>,然后比较 <变量名> 和 <终止> 的大小,若 <变量名> 小于等于 <终止> 则进入循环,否则不进入;每次循环结束后 <变量名> 都会被修改成 <变量名>+1 并继续执行循环,一旦 <变量名> 大于 <终止> 立即终止循环。
变量名是一个以小写字母开头的词,不与作用域未结束的其它变量(包括 n)重名。<起始> 和 <终止> 均为作用域内除 <变量名> 之外的变量或常数。
* E 表示之前离其最近的未结束的函数或 For 循环的结束,同时该函数或循环建立的变量作用域结束。
* <函数名> <参数> 表示以 <参数> 为参数调用该函数。<参数> 为某个作用域未结束的变量或常数。
* S 表示时间复杂度标志语句。
程序的最后一个函数名必定是 Main,执行程序相当于以输入的参数 $n$ 调用一次 Main 函数。
为了方便你计算时间复杂度,LCR 定义程序运行时间为标志语句 S 的总执行次数。
可以证明,当 $n$ 充分大(即,对于每个给定的程序存在一个常数 $M$ 使得 $n>M$ 时后面的结论均成立)时,S 的总执行次数是一个关于 $n$ 的多项式。规定渐进复杂度的次数 $w$ 为多项式最高次项的次数,常数因子 $k$ 为多项式最高次项的系数。即 $T(n)\sim kn^w$。
LCR 身经百战,见得多了,自然不会出现语法错误这种低级失误啦!