这是我整理的第二个CF好题专辑了。
整理这些题目只是因为这些题目确实很棒,我在做完这些题目之后的第一感觉是这些题目真的很好。
从今年暑假开始我几乎每天一场CF,总体感觉是CF的题目质量很高,很多题目你必须要转很多个弯或者从反面思考或者注意很多细节,思考量一般都比较大,而这些就是让你的思维徒增猛进的题目,不做真是可惜啊。
一、CF 126B Password http://www.codeforces.com/problemset/problem/126/B
KMP巧妙应用。先找符合既是前缀又是后缀的子串,再判断是否在串中出现。这样转换就将三个限制变成二个,第三个限制变成判定性条件。解题报告见Here
二、CF 123A Prime Permutation http://www.codeforces.com/problemset/problem/123/A
并查集+数论+模拟。给一个串str,len是str的长度,求出小于len的素数primei,然后问我们通过重组str是否能使得是primei倍数位置的字母都一样?每次选primei倍数位置的最大父亲集合,然后把所有位置都并到那个集合,其余集合清0.必须在同样的位置都靠到一个位置。然后记录每个字母出现的位置,把最多的字母填到最大的集合区,如果填不下则说明没办法重组出一个符合条件的字符串。赛后看了解题报告,说偶数都必须一样,然后2*p<n那么p的倍数都必须相等,2*p>n则不受限制,因为素数2的特殊性使问题变得十分简单,可能只要50行左右的代码,我洋洋洒洒地写了140多行,咳,要注意观察题目,发现一些重要性质,这样就可能优化代码。
三、CF 115B. Lawnmower http://www.codeforces.com/problemset/problem/115/B
贪心。由于每次必须将整行的走完,而且不能变换方向,由此可知每次都是走极端。
四、CF 114B. PFAST Inc. http://www.codeforces.com/problemset/problem/114/B
简单的状态压缩。这场比赛真是被坑到了,一直以为这题可以贪心,换了两种方法都没办法ac,为了赶速度赶成脑残了。
五、CF 112D. Petya and Divisors http://www.codeforces.com/contest/112/problem/D
因为是从后往前找,那么只要找当前的因子最后再哪里出现,如果出现位置小于n-那么这个因子就合法,否则就不合法。每次都要更新当前的因子出现的位置。
六、CF 222 C. Reducing Fractions http://www.codeforces.com/problemset/problem/222/C
给定分子和分母集合,集合元素最多10万个,分子为他们的乘积,分母也一样。现在要对他们进行化简,要求输出化简后的两个集合。
这题我学到一种很经典的用于求一个数质因子的方法,在筛选素数的时候记录每个数的最大素因子,然后就可以很快地枚举出他的所有素因子,比如一个数n,他的最大素因子为prime[n],那么n /= prime[n],这时候的n又有一个最大素因子,如此这般就ok了。不过这种写法有个约束条件,n不能过大,过大的话筛选的操作量很大。
题目要求输出的分子分母集合元素不超过10万,这暗示着我们只要在输入的基础上进行化简,也就是用分母的素因子去化简分子,用分子的素因子去化简分母。
七、CF 225 C. Barcode http://www.codeforces.com/problemset/problem/225/C
DP.要求把乱七八糟的图形刷成黑白相间的图形,且每列的颜色必须一样,然后连续的黑或连续的白的列数大于x且小于y。本题的n没什么用。预处理出列刷成白需要几步,刷成黑需要几步。
设dp[i][k]表示i之前都满足情况且第i列为颜色k的最少花费,dpi][k] = min(dp[i][k],dp[j][1-k]+cost[[i][k]-cost[j][k])(i-j>=x && i-j<=y),复杂度O(m^2)。据说O(m^3)也能过
八、CF 229 A. Shifts http://www.codeforces.com/problemset/problem/229/A
枚举列,把每行移到1到这列的最少步数相加,求最小值。关键部分是求每行的最小步数,最简单且可行的做法是二分查找向右下标最小的那个1,再二分向左查找下标最大的那个1,这样复杂度O(n*m*log(m)),CF时限很宽松可以过。我的做法是用O(n*m)的时间去预处理,把每个位置左边第一个的1和右边第一个1的位置计算出来,预处理完O(n*m)枚举,O(1)计算步数。
九、CF 93 A. Frames http://www.codeforces.com/problemset/problem/93/A
很好地一道题目,并不难但要想得比较清楚才能AC。a在ra行ca列,b在rb行cb列,如果ra==rb,都只要一次。如果ra==rb+1,且ca==1&&(ra!=lastr&&cb==m||ra==lastr
&&cb==lastr)的时候只需要一次,从[ra,ca]开始拉到下一行或者拉到结尾。如果ra和rb中间还有一行或者多行,那么分三种情况讨论:1次的,2次的,3次的。1次的是ra和rb之间的都是满行。2次的和上面的ra==rb+1的类似,多一种当ca-1==cb的时候我们可以竖着啦两个矩形覆盖它们,其余的都是要3次。还有一种情况要特判,当m==1的时候全部都只要1次,竖着拉一次就能完成要求。
十、A. Newspaper Headline http://www.codeforces.com/problemset/problem/91/A
给定一个A串,一个B串,我们用不同的去除某些位置的A串组成B串,问最少需要几串?首先要想到用A串去除最少的位置去匹配B中一部分,当匹配到i位置时,我们要知道i-1匹配到哪个位置即为pre,然后找A串中pre位置以后下一个B[i]位置,找不到从头开始找,如果从头开始找找不到就无解,找的到又找最近的那个,这样一直找,看看要从头开始几次就好。
本文ZeroClock原创,但可以转载,因为我们是兄弟。