题目名称 | easyfinding | ski | allow | calc |
时间限制 | 1s | 1s | 1s | 1s |
空间限制 | 128MB | 128MB | 128MB | 128MB |
注:1、输入输出文件名为*.in和*.out,其中*是英文题目名称。
2、所有输入文件最后有一个换行符号
第一题:easyfinding
【题目描述】
给一个M行N列的01矩阵,让你选出一些行(不一定选出全部行)使得每一列都有且只有一个1。其中M<=16,N<=300。
【输入格式】
输入含有多组数据。以文件结束符(eof)为结束。最多会有500组。
输入之间会有梯度,也就是不是每组输入都是500组。
对每组数据,第一行:两个由空格隔开的整数: M和N。然后是M行每行N个等于0或者等于1的整数,整数之间由空格隔开。
【样例输入】
3 3
0 1 0
0 0 1
1 0 0
4 4
0 0 0 1
1 0 0 0
1 1 0 1
0 1 0 0
【输出格式】
对每组数据输出一行,如果可以达到题中要求,输出’Yes’否则输出’No’。均不包括引号。
【样例输出】
Yes
No
第二题:ski
【题目描述】
FJ想要带着 Bessie 一起在科罗拉多州一起滑雪。很不幸,Bessie滑雪技术并不精湛。Bessie了解到,在滑雪场里,每天会提供S(0<=S<=100)门滑雪课。第i节课始于Mi(1<=Mi<=10000),上的时间为Li(1<=Li<=10000)。上完第i节课后,Bessie的滑雪能力会变成Ai(1<=Ai<=100).
注意:这个能力是绝对的,不是能力的增长值。
Bessie买了一张地图,地图上显示了N(1<=N<=10,000)个可供滑雪的斜坡,从第i个斜坡的顶端滑至底部所需的时长Di(1<=Di<=10000),以及每个斜坡所需要的滑雪能力Ci(1<=Ci<=100),以保证滑雪的安全性。Bessie的能力必须大于等于这个等级,以使得她能够安全滑下。
Bessie可以用她的时间来滑雪,上课,或者美美地喝上一杯可可汁,但是她必须在T(1<=T<=10000)时刻离开滑雪场。这意味着她必须在T时刻之前完成最后一次滑雪。
求Bessie在实现内最多可以完成多少次滑雪。这一天开始的时候,她的滑雪能力为1.
【输入格式】
第1行:3个用空格隔开的整数:T, S, N。
第2~S+1行:第i+1行用3个空格隔开的整数来描述编号为i的滑雪课:Mi,Li,Ai。
第S+2~S+N+1行:第S+i+1行用2个空格隔开的整数来描述第i个滑雪坡:Ci,Di。
【样例输入】
10 1 2
3 2 5
4 1
1 3
【输出格式】
一个整数,表示Bessie在时间限制内最多可以完成多少次滑雪。
【样例输出】
6
【样例解释】
滑第二个滑雪坡1次,然后上课,接着滑5次第一个滑雪坡。
第三题:allow
【题目描述】
作为创造产奶纪录的回报,FJ决定开始每个星期给Bessie一点零花钱。
FJ有一些硬币,一共有N (1 <= N <= 20)种不同的面额。每一个面额都能整除所有比它大的面额。
他想用给定的硬币的集合,每个星期至少给零花钱C (1 <= C <= 100000000)。请帮他计算他最多能支付多少个星期的零花钱。
【输入格式】
第一行:两个由空格隔开的整数: N和C。
第2到第N+1行:每一行有两个整数表示一个面额的硬币:硬币面额V (1 <= V <=
100,000,000)和Farmer John拥有的该面额的硬币数B (1 <= B <= 1,000,000).
【样例输入】
3 6
10 1
1 100
5 120
【样例输入解释】
FJ想要每个星期给Bessie六美分。他有100个1美分硬币,120个5美分硬币,和一个10美分硬币。
【输出格式】
第一行:一个单独的整数,表示Farmer John最多能给Bessie支付多少个星期至少为C的零用钱。
【样例输出】
111
【样例输出解释】
FJ可以在一个星期超额付给Bessie一个10美分硬币。然后接下来的10个星期每星期付给Bessie两个5美分硬币。最后100个星期每星期付给Bessie一个1美分硬币跟一个5美分硬币。
第四题:calc
【题目描述】
calc,一个多么简练的名字。
题目也很简练。给以多项式形如,让你把它变形成为.。如果看不懂数学符号请看后面的样例及解释。
【输入格式】
第一行一个两个整数n和t。1<n<=200,-10<=t<=10。
第二行n+1个整数,顺次为a0,a1,a2,a3...an.
【样例输入】
2 1
1 0 2
【输出格式】
输出一行,为n+1个整数,为b0,b1,b2,b3..bn。数间用一个空格分开。行末不要有空格。
【样例输出】
3 4 2
【样例解释】
原来的多项式是1+0x+2x2 ,变形后变成了3+4(x-1)+2(x-1)2 。
【出题人温馨提示】
所有数据输出的bi不会超过400位。有若干个数据bi不会超过64位整数的范围。
出题人对以上提示具有最终解释权。
题解:
‘’
091107解题报告
第一题 easyfinding
算法:搜索。
这道题是送分题。不过最后两三个点范围比较大。需要对算法进行优化。
基本的思想是枚举2^N种选择情况。看是否有满足条件的组合。
可以预处理出来必然矛盾的行(即在同一列都含有1)。然后用位运算存储当前选择了哪些行,作为参数传递下去。这样在搜索中的判断就只需要O(1)的时间,并且是速度很快的位运算。
进行了如上的预处理之后,判断覆盖完也就不必使用数组。只需记录每行有多少个1,把选择的行的1的数量累加起来,当总数达到N时就可以判断有解。这样判断跳出也只要O(1)的时间。
经过了这两个优化之后,搜索效率就提高了很多。
据说此题还可以用一种叫dance link的东西优化。
第二题 ski
(本题std为pascal)
算法:动态规划。
此题与经典Dp类似。状态相当明显。显然是f[i][j]代表第i分钟能力值为j的最多能滑雪的次数。
转移如下:
f[i][j]à上课àf[i+课时][新能力]
or f[i][j]+1 à滑雪àf[i+需时][j]
但是一个问题出现。可供滑雪的山坡数N<=10000。那么在转移的时候是否需要枚举滑哪个山坡呢?这样不就超时了么?
当然不是。
首先,我们明确一点,如果一个山坡耗时大于等于另一个,难度也大于等于另一个,那么这个山坡肯定没用。
所以
第一步:我们只需记录各种难度的山坡耗时最短的值。记为need[i]。
第二步:从小到大循环need[i]=min(need[i-1],need[i])。
这样求出来的need数组是单调不降的。
显然,这种情况下,当我能力为i时,最优的选择就是need[i]。
于是第二种转移只需要O(1)的时间。
而第一种转移因为上课总数很少,所以只有在特定的时间点才做这种转移。
具体实现方式我想到的有:
1.使用邻接表存储(参考程序做法)。复杂度O(100*S)。
2.在每个时间点内进行枚举,把符合要求的课程存进数组。复杂度O(N*S+100*S)。
3.每次转移暴力查找。复杂度O(N*S*100)。
因此此题最优复杂度是O((N+S)*100)。
现在看来此题不是很简单……不过这题很好,既需要掌握经典的DP思路,也需要灵光的闪现。
第三题:allow
算法:贪心。
先说方法。
原则是:先用大的,到再放一个就要超过需求的时候开始向下找小的。按这样的要求一直找到最小的。如果最小的不够,那么最小的不动,倒回到目前还有的次小的,使用一个即可。
因为前面是按照只要一个就会超的原则,所以只要钱的总数足够,再加一个就一定可以满足这个月的了。如果前面的都没有剩的了,那说明已经搜刮殆尽。退出循环。
钱的数量会很多,如果每次只算一个月的话会超时两个点。因此每次算出一个方案,就看现在的钱可以供多少个月这样的方案。直接累加答案并且减去需要的钱即可。采取这样的方式,每两次计算就可以使某个面值消耗殆尽。因此计算次数不会超过2N次。复杂度O(N^2)。
方法就是这样。
因为本人数学的烂,我也提供不出一个严格的证明。我只能说说我的想法。
这道题最关键的一个条件:大的一定能被小的整除!
这就导致一个显然的结论的出现:当有若干张小的面值叠加可以和一个大面值等价的时候,一定是用大面值。
现在的问题是,如何证明当使用大面值只亏一点,而小面值需要很多张的时候,使用小面值更优。
我们来“说明”一个简单的情况。只有两种面值。
设b是较大的面值,c是较小的面值。
某种方案下可以用xb+yc,也可以用(x+1)b.
如果我们一直使用(xb+yc),最后仍然剩下c,那么这种方式肯定不会劣。
如果最后会剩下b,那么最后我们依然会被迫使用xb。其实总的方案没有变,只是顺序变了而已。
姑且就这样吧……求数学大牛证明之。
好,以上是我自己的yy。下面抬出官方证明。
首先假定我们是按钱递增的顺序来取的,即下一个月的工资肯定大于等于这个月的工资。并且每一次取都不会有多余的钱币。也就是说不存在可以删除一个钱币却仍然满足限制的月份。
容易看出这样的规定与原题等价,并且由于不会取多余的钱币一定会比取多余的钱币优。
(要证明最优,只需证明它比另外所有方法优)
在这种假定下,我们就可以轻易发现,如果前期用亏着用大面值一定不会好。举个例子:限制是38,有5分的和一分的。可以7*5+1*3,也可以8*5。但如果采取8*5的话,你会发现那三个一分永远用不出去了!因为之后月份的工资必须大于等于40。而里面如果有一分的话,去掉它依然满足条件,这就与我们前面的规定不符。这样就相当于白白浪费掉了一个五分。
由此,有上面的算法。
第四题:calc
算法:二项式定理+高精度。
这道题相信大家都在数学中见过。基本算法很简单,从高次到低次一位一位确定。每确定一个bi,就把那个二项式展开,修改bj(j<i)的值。二项式定理的内容是
(a+b)^n=c(0,n)*a^n+c(1,n)*a^(n-1)*b+c(2,n)*a^(n-2)*b^2……+c(n,n)*b^n
因此如果不考虑高精度的话,这个复杂度是O(N^2)。
这道题的高精度比别的多一个东西,就是符号。因为符号的存在,加加减减需要另加判断。
如果原运算是加,同号使用加法符号不变,异号使用大绝对值减小绝对值,符号取被减数的。原运算是减,同号用绝对值大的减小的,如果原被减数绝对值小于减数那么修改符号,
在展开式子的时候,只需要用到高精度乘除单精度。即运用二项式定理,从x的高次到低次计算,每次把上一次的值乘一次除一次再乘上一个t即可。
关于这道题答案长度问题,我也不能严格证明它小于等于多少。不过400位应该是足够的。
此题代码较长。