刷题记录:Codeforces Round #725 (Div. 3)
Codeforces Round #725 (Div. 3)
20210704。网址:https://codeforces.com/contest/1538。
感觉这个比上一个要难。
A
有一个n个数的数组,我们每次只能拿走最左边/最右边的数。想把最大/最小的数都拿走,最少拿几次。
读入的时候就记录下来最大最小的位置,设左边位置为x,右边位置为y。要不【从左边拿直到拿走y】,要不【从右边拿直到拿走x】,要不【从左边拿直到x+从右边拿直到y】,取个min就可以了。
B
大水题,首先判能不能整除(平分),然后对average以上的人下手。
C
有一个n个数的数组,我们要统计pair的个数。
什么样的pair呢?i<j,并且l<=a_i+a_j<=r。
我的想法是二分搜索:先排序,然后对每一个a_i:
- 二分搜索得到a_j的范围;
- 因为要求i<j,所以【a_j的左边界=max(原左边界, i)】。
- 如果a_j范围已经变成空集,break。再往下肯定更是空集。
- ans+=a_j范围大小。
D
这个题让我怵了半天……最后看题解才明白怎么做。
给我们三个数,abk。我们必须精确完成k次操作,不多不少,使得ab相等。
一次操作:拿一个数除a,或者除b。当然,要用它们的因子(大于1)来除。
题解:我们的目标是a==b,最多做多少次操作?拿a的质因子一个一个除a,然后拿b的质因子一个一个除b,最后a和b都是1。操作次数就是【a质因子个数+b质因子个数】。
最少呢?如果已经a==b,0次;如果a是b的因子,1次;其余情况,a除a本身,b除b本身,2次。
如果k不在[最少次数,最多次数]的范围内,肯定不行。如果在,一定可以吗?
我们可以一次除【两个质因子乘积】,这样就用一次操作替代两次操作。感性上想,通过这种办法就可以取到最小最大之间所有次数了。
但是最后要注意一个事情!如果a==b,那么没法一次完成。一次的话就只能除一个人,除了之后它和另一个就肯定不相等了,所以不行。
然后是一些编程上的问题:其实不需要打巨大的prime表,只要保证表内最大的质数比sqrt(1e9)要大。用这个表对一个数进行质因子分解,最后得到一堆质因子和一个巨大的丑陋数。如果这个丑陋的数不是质数,那么它=x*y,【xy中更小的那一个】最大只能到sqrt(丑陋数)。如果sqrt(丑陋数)在表里,这个丑陋数肯定会被分解掉。
丑陋数≤1e9,因此【表内最大的质数比sqrt(1e9)要大】就可以了。突然发现其实是很简单的事情,我怎么写了这么久……总之就是,勇敢地认为最后剩下的丑陋数也是质数,这样就能正确统计质因子个数了。
E
给我们很多语句,语句共有两种:字符串赋值(声明字符串变量)和字符串加法(append)。求作为【最后一个语句返回值】的字符串中"haha"字串的个数。
一开始直接模拟的,然后内存爆掉了。给我50条语句,每次都是“a=a+a”的样子,最后会得到长度为2^50的字符串。嗯…教训就是,看见貌似很简单可以直接模拟的题,多想一步。真的能直接模拟吗?
正确做法是,对于字符串赋值,记录【haha个数】【串首3个字符】【串尾3个字符】。对于字符串加法,结果首先是两个【haha个数】相加,在此基础上考察【前串串尾】和【后串串首】拼起来会不会产生新的haha。
如何考察呢?只要看hah+a,ha+ha,h+aha三种情况就可以了,出现一种就++一次。然后记录新的字符串,用【前串串首】【后串串尾】作为新的串首串尾。
最后注意一个事情:如果字符串长度根本不足3,那么串首串尾就赋值为【这个短字符串本身】。拼接的时候,如果原来长度不足3 现在长度有3,要注意维护串首串尾。
F
给我们两个整数l和r,不断++l直到l==r。统计这个过程中【数位变化】总次数。
数位变化:如11->12,变化1。999->1000,变化4。109->110,变化2。
一开始想法有点迷,虽然样例过了但应该确实是错的…不管那个错想法了,题解是这样的:
首先,个位要从l的个位变到r的个位,变r-l次。
然后,十位要从l的十位变到r的十位,变r/10-l/10次。
以此类推。
写一个while循环,每次r/=10,直到r==0。
然后说一点偏玄学的想法:给1e4个测试,每个测试的lr范围都是1e9,限时2s。所以不可能是模拟,也应该不是复杂度常为o(n)o(n^2)的dp。应该是从数据入手一下子算到答案的解法,不是那种一层一层积累的dp。
G
有两种物品,分别有xy个。我们要制作礼物包,一个包要不是【a个第一种物品 b个第二种物品】,要不是【b个第一种物品 a个第二种物品】。问最多可以做多少个包。
很自然(其实是看见算法标签里有greedy)的想法是,用a和b的差距补x和y的差距。设a≥b x≥y,那么多打几个【a个数量多物品 b个数量少物品】的包,即多消耗数量多的物品,直到剩余两种物品数量差不多。然后一个ab包一个ba包,争取每次消耗都相等。(并不会严格证明,也不想证……)
按照这个思路写程序。注意各种特殊情况的识别:
- 打(x-y)/(a-b)个偏心的包就可以消除数量不平衡了。但是真的能打这么多包吗?我们只能尽量多打,打包数量是取min后的结果。
- a==b的时候,除a-b会出现除0错误哦,需要特判。
- 最后没法打【ab包+ba包】了,但说不定还可以打一个【ab包】或者【ba包】。(我其实不清楚是否可能出现这样的情况。)反正最后判一下总是没错的。