NOIP2005提高组 解题报告
1.谁拿了最多奖学金
水题,简单的数据处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
2.过河
可以考虑动归。f[i]表示跳到第i个位置需要踩到多少石子,f[i]=min{f[k]}+rock[i] (s<=k<=t,当i处有石子的时候rock[i]=1,否则为0)。显然L<=10^9,O(n)会时间空间双爆,考虑压缩。
因为石子数量比较少<=100,所以中间一定会产生许多的空长条,如果我们能够压缩这些空长条,那么总的长度就会小得多了。可以证明,如果相邻两个石头的距离Q>=s*(s+1),那么一定可以使用s,s+1两种步长跳过。可以参考noip2005 过河 解题报告 @ N_C_Derek
因此,对于所有相邻的两个石头距离b[i]-b[i-1]>=s(s+1),则从第i个点开始,后面的每个点都向左移动b[i]-b[i-1]-s(s+1)个单位。这样一来,L被压缩到10010,m<=100,对于O(m^2)的预处理和O(n)的DP毫无压力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
3.等价表达式
这题大体的思路是:随机选取几个a,分别带入原式和目标式子,如果得到的答案都相等,那么就可以认为目标式子=原式。
这题的难点不再于算法,而在于编程的熟练度。大部分人都使用栈来操作,我没用栈而是用递归分治的思想来解决,代码长度和编程复杂度相对来说较低。具体做法如下:
对于每一个待机算的字符串s,我先对s进行处理,去除空格和括号,使其仅留下常数和运算符。比方说-3(x+1)-3^2,处理完后就变成了-3x+1-3^2。同时我又记录每一个字符串和常数的深度,所谓深度就是指它被几个括号包住。上面那个例子,处理完后的字符串中每个字符的深度分别为0001110000。
每一次函数work(l,r)处理字符串的区间[l,r],并返回计算的值。分治的方法如下:找出取出[l,r]中深度最低的符号,如果有多个深度相同的符号那么取优先级最低的(优先级从大到小排列如下:^、*、+-、常数)。假设这个符号是-,位置是p,那么work(l,r)=work(l,p-1)-work(p+1,r)。有三个小细节需要注意:- 如果当前取出的符号为-,那么所有[p+1,r]中和当前-号深度相同的+号都得变成-号,-号都得变成+号。
- 因为xyz=(xy)z != x(yz),因此寻找深度最小并且记录位置的时候,位置要尽量靠后。
- 如果计算使用浮点数,x^y的时候千万不要使用exp(y*ln(x)),这样当x<=0时果断出错,正负性也难以解决。因为y为整数,所以for一遍吧。
显然对于题目给定的数据范围,int64也无法承受。不建议使用浮点数,因为其太容易出错了。可以发现题目中的操作只有+-*^,mod对这些运算符均无影响,因此可以考虑使用整型+取模。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
|
4.篝火晚会
这题是构造算法。 可以参考noip2005(提高组)讲解 @Des,讲得很详细。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|