【c++每日题】【2022年11月30日】

题目名称

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位应该是足够的。

此题代码较长。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值