2016BITCS小学期程序设计简要题解

2016BITCS小学期程序设计简要题解

球体问题 By CFhM_R

设球缺的高为h,由于题目中说明d>max(R1,R2)且d<(R1+R2),所以两个球“镶嵌”而损失的体积不会超过球体的 1/2 , 因此直接积分可以得出球的体积公式。

正视球缺,设由于“镶嵌”损失的劣弧所对的圆心角为 θ ,考虑球表面积的积分方法,对 θ 取值限定范围易得 S=2πRh

注意本题的 π 的新的定义


修剪草坪 By CFhM_R

可以证明,对于一个合法的点,必为这一行或这一列的最大值,否则需要改变一行或一列的值来达到这一值。


扫雷 By CFhM_R

直接模拟即可,可以把所有有雷的位置变成1,其他为0, O(n2) 扫描时对每个为0的点输出其周围8个人的和即可。


合并果子 By CFhM_R

经典贪心。

  • O(n2) 暴力可做,由于数据范围不大,每次取最小的两个合并后加入原数组中直到剩下最后一个即可。

  • O(nlogn) 解法:首先证明每次合并的结果 是非递减的,因为每次合并都取当前堆中最小的两个进行合并,所以本次合并的结果一定不小于前次合并的结果,否则推出矛盾。

    因此可以用两个数组对原始的果子和合并后的果子分别进行维护,对原始果子按照升序排序后两数组都是非递减的,每次更新仅取数组头部的较小者进行合并即可。

  • O(n) 解法:这个优化是对于排序的,因为题目中说 1<=ai<=10000 ,所以可以利用数组下标的线性性质来维护元素的序关系(计数排序),即一个数组cnt[],对于一个元素 ai ,进行操作cnt[ ai ]++表示该元素出现了一次,之后顺序遍历整个数组,寻找值不为0的元素对应的下标即为果子的数目。


传送带 By CFhM_R

考虑可以加速的部分是优先让快的更快还是慢的变快,显然 v0v 的转变不如 v 对结果的贡献大,因此得到贪心策略是优先让最慢的变快,注意讨论不能使完整的一段路加速的情况。


贪婪的你 By CFhM_R

倒着贪心,按截止日期从大到小排序,对每个日期选择分值最大的。


蜜汁序列 By V5ZSQ

贪心,因为后面数被分成几段并不会影响前面的数,故从后往前扫,给出两个结论 :

      1. 每次从后往前扫遇到的第一个负数一定是某个段的末尾。如果这个负数是某一段中间值,由于其后面都是非负的,而且后面的数影响不到前面的前缀和,那么将后面的非负值单独拿出来作为一个段显然更优; 
      2. 每次从后往前扫遇见第一个负数之后,不妨令这个负数下标为i,往前找离i最近的j使得a[j]+…+a[i]>=0,从j到i作为一段显然是合法的,且是最优的,因为如果选择一个小于j的k,使得k到i作为合法的一段,显然不如分割成k到j-1作为一段,j到i作为一段(由k到i合法和j到i合法轻易知道k到j-1和j到i也是合法的)。       所以做法就是从后往前扫,遇见非负数直接将其看作一段,遇见负数就往前找并且累加和,只要累加值非负就当做一段。


a+b By CFhM_R

直接用字符串模拟即可,注意特殊情况

  • 给出前置零和后置零
  • 小数加和变成整数去掉小数点
  • 整数以小数形式表示
  • 没有整数部分仅有小数点+小数部分

一夜发白《千字文》 By CFhM_R

字符编码,每次读字符并利用位运算判断这个字究竟是几个字符组成的,之后读入剩下的字符并且用16进制表达。数据比较水最多只有3个字符的情况。


9的统计 By CFhM_R

高精度计数。首先将求区间 [L,R] 数量转换为求 [0,R] [0,L] 的数量后二者做差。

其次简单推导可知,一个数 n=anan1a1a0 ( ai 表示这个数的第 i 位),则[0,n]的数字中包含9的个数为 ni=1ai10iai9i ,原理即算出所有数字种数减去不含9的,这个公式可以适用于所有不含某一特定数字的数量。

最后是一些细节问题,比如本题需要用压缩进制法节约空间,由于一个int最多可以完整表示8位数字的范围,所以我们采用8位压缩,即一个int表示大数的8位,这样可以节省不少的空间,而且每两个int之间的运算可以直接进行,记录进位即可。


识别条形码 By CFhM_R

由于至少有一个宽条,所以认为最大的一个是宽条,确定一个区间,之后对每一个条都按他是宽的计算区间求交,窄的转换成宽的计算,如果发现有两个交集为空说明非法,否则有解。


平面上的邮局 By CFhM_R

对x,y坐标分别排序后找中位数。


比赛计分问题 By CFhM_R

结构体排序裸题。

注意就是并列的情况,两个人并列第一之后接下来的人是第三。


谁更机智 By V5ZSQ

看似博弈,其实是dp,因为题面已经给出了最佳策略,按最佳策略模拟即可。首先对所有数排序,以dp[i]表示剩下前i个数时,先取数的人能够达到的分数差最大值,那么有 

dp[0]=0 
dp[1]=a[1]-dp[0]=a[1] 
dp[2]=max(a[2]-dp[1],a[1]-dp[0])=max(a[2]-dp[1],a[1])=max(a[2]-dp[1],dp[1]) 
dp[3]=max(a[3]-dp[2],a[2]-dp[1],a[1]-dp[0])=max(a[3]-dp[2],dp[2]) 
…… 
dp[n]=max(a[n]-dp[n-1],dp[n-1]) 
O(n)递推即可 


电话号码问题 By CFhM_R

首先判断合法性。

读入之后转换字母映射,去掉连字符,之后看总位数是否为7位,以及第一位是否为3或6。

其次判重。

因为内存空间不足所以依然要进制压缩,这里用二进制表示一个状态的存在或不存在,运用一个简单的道理:商乘除数加余数,我们可以把一个数分解成他除以某个数的商以及余数,余数又可以用二进制位来记录。一个int恰好32位,所以模32。

新开数组记录重复的部分,每次线性查找就行,题目说了这个不多,所以不需要优化。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值