[置顶] codeforces好题集合 (持续更新)

再次感到智商的不足,所以决意以后必须多刷cf了,cf不仅锻炼智商,还能锻炼代码能力,锻炼手速,是非常不错的,以后要多做,就算现在被虐成翔,相信一年之后也会有很大的提高。让我们 一起享受智商被碾压 的快感把


首先是最近一场cf的div1的AB两题

CodeForces 571A

题目链接:http://codeforces.com/problemset/problem/571/A

题意:给你三根木棒长度为a,b,c,然后给你长度 l 的木棒,让你可以把a,b,c随意加长,但是加长的总和不能超过l的方案数(可以不加长)

题解:我看到这题基本没多少想法,就算有不敢说是对的,没有很好的方法解决

那就开门见山把,用题解的方法,这题正着比较难,所以就先求出所有分棒子的情况,然后去掉里面不能构成三角形的情况(orz)

所有分棒子的情况,就是个组合问题,假设有a,b,c分别增加了x,y,z,x+y+z=i<=l  (0<=i<=l)

就是把i长度的棒子切成三段,切两刀,(假设第一刀一定在第二刀的前面或者同一处)

长度i的棒子,一共有i+1处可以切,因为可以分给a长度0-i,所以有i+1刀

如果第一刀切0,第二刀也有i+1种

第一刀切1,第二刀就有i种切法

所以总的方法就是(i+1) +(i) + (i-1)+……+1=C(i+2,2);

0<=i<=l,所以所有分棒子的方法就是C(2,2)+C(3,2)+……C(l+2,2)

根据排列组合公式,C(2,2)=C(3,3),+C(3,2) =C(4,3),+C(4,2)=C(5,3)

所以C(2,2)+C(3,2)+……C(l+2,2)=C(l+3,3)  这是总的分棒子 的方法


然后就是求不能构成三角形的情况啦,我感觉这个考虑方法比较巧妙

先考虑把a增加之后的边考虑成最长边并且使三角形不成立,就是b+c=a+i

然后就是考虑从a+i,a+i+1……a+l,这些情况,当a+i,b,c构不成三角形的时候,要把剩下的l-i的长度分给b,c,并且使b‘+c’<=a+i

此时能够分给b,c的长度为min(l-i,a+i-b-c)=x;然后将这段分给b,c的情况,就是C(x+2,2)

为什么呢,同上,就是长度x的棒子,切两刀,前两段给b,c,最后一段扔掉好了

这样就是最长边是a所在的边的不能构成三角形的情况

b,c同理

并且这样考虑不会有重复,因为你定的最长边就不一样

代码十分简短,这就是cf的魅力,我要 继续努力,终有一天争取能在div1立足,脑洞开之

AC代码:http://paste.ubuntu.net/12229055/

/****************************************************************华丽的分割线***********************************************************************/

575D :Tablecity http://codeforces.com/problemset/problem/575/D

这题目没有输入,题意比较呵呵,我都没理解,后来年神带我过了之后感觉这题还是非常的好

题意:给你个2*1000的长方形,然后上面有个小偷,小偷每次可以往6个方向逃窜,左右,左上左下,右上右下,然后你是警察,你每次可以派两个警察进行搜查,就是可以搜查两个点,问你最小需要多少次,你肯定可以找到小偷

题解:刚看完题是不是很呵呵,所以我还练习的不够,瞎找肯定是不可能的,所以肯定是有规律的,两个警察必须在同一竖行,这样可以把长方形的宽2都填满,然后一格一格的搜索,因为发现小偷每次是只能左右的移动,如果你两个搜索点叠着,那么上下都可以不考虑了,等于就是一个1*1000的长方形,里面你用一个警察去搜索小偷,然后这要应该考虑格子的奇偶关系,如果小偷开头在偶数,你也在偶数,那么你从最后一格1000开始往前走,肯定能找到,如果小偷在奇数,你在偶数,那么肯定最后会错过,当你从1000搜到1的时候,小偷这会在偶数,下一步小偷在奇数,你应该也从奇数开始搜,就是999开始往前,所以一共最少1999次可以肯定找到

代码三行,就不贴了,这题目还是不错的,我现在是阅读理解能力和脑洞都不足啊还需努力

一天一场cf,健康生活五十年啊

/*********************************************************************************************************************************************************/

575H Bots http://codeforces.com/problemset/problem/575/H

题意:给一个点,然后可以走红色或者蓝色的路,然后走到底之后,从根节点到叶子节点的路上面一共有n条蓝色n条红色边,问最后树里有多少个点

题解:比如第i层,走了i条边,所以在第n+1层的时候有两个点只能走一种颜色了,然后在i>n的情况下,每次都有一些点只能走一个颜色,可以用组合数求出来,                   

就是2*C(i,i-n)个点只能走一种颜色,其中要用逆元求解一下组合数

AC代码: http://paste.ubuntu.net/12319046/


/*********************************************************************************************************************************************************/
  573B : http://codeforces.com/problemset/problem/573/B
题意:给你n个东西,每个东西有高度,然后类似于搭积木一样,一次操作可以把最外围的方块都去掉(至于什么是最外围,就是他周围至少有一边没有方块),然后问你最少多少次操作可以把所有方块都去掉
题解:一开始我想的是二分,但是二分之后不会判断什么时候已经被去掉了
看题解说的是做一次操作h[i]=min(h[i-1],h[i]-1,h[i+1]),类推操作k次就是h[i]=min(h[i-j]-(k-j),h[i+j]-(k-j))
唉都提示到了这里我居然都没写过,其实不需要用二分,应该考虑每个i,最少操作多少次能到0,然后求这些操作的最大值
然后考虑h[i]=min(left,right),left=h[i-j]-(k-j),left=0,k=h[i-j]+j,就是找i前面的h[i-j]+j最小的,换言之就是找h[t]+i-t;最小的,那么只要设个值,每次记录h[t]-t的最小值,然后每个i的时候+i更新一下就好了就是这个点的k,right也同理,就是从n开始往前遍历,找h[t]+t的最小值,然后最后-i
然后就是边界值的问题,h[0]=0,h[n+1]=0。。。。h[0]-0=0,h[n+1]+n+1=n+1,所以左边从0开始算,右边从n+1开始算
唉脑洞还是不行,思维能力也不如以前啊,最近成为了模版流,是时候走起一波cf了,提升一下脑洞
AC代码 : http://paste.ubuntu.net/12326306/

/********************************************************************************************************************************************************/
577B: http://codeforces.com/problemset/problem/577/B
题意:给你n个数,在其中选出一些数,能否被m整除
题解:这题一开始想的是,先全部模m,然后背包一发,不过n是10的6次,m是10的3次,10^9的复杂度刚不住啊,然后就秒躺
其实我以前用过bitset优化背包,经过实践bitset是可以优化10^9次的背包
就是每次输入一个数模m之后得到x做位运算,先左移x位与自身取或,为了防止溢出再右移m位与自身取或,每次做完这些之后要把x为变成1,因为这是背包,最后考虑0位是不是1就行了(为啥不是考虑m位,因为如果就输入1个数,输入的是0呢)
AC代码 : http://paste.ubuntu.net/12358422/

然而这肯定不是标准解法啊
其实这题可以用抽屉原理优化复杂度,n个数,构造n个 a1,a1+a2,a1+a2+a3,。。。a1+a2+。。。+an,这些数模m,得到n个余数,如果这n个数中有数字模m得0的,那么就找到了,如果都没有0的,那么最多有m-1种余数,此时有n个余数,只要n>m-1,那么必定有两个余数相同,然后这两个数字相减,得到的就是一些数的和,可以整除m,所以说n>=m的时候必定是YES,这样就可以把n优化成10^3,背包就变成了10^6,然后写背包的时候注意溢出什么的就行了
AC代码  :  http://paste.ubuntu.net/12358817/

/********************************************************************************************************************************************************/
第一次做div2的最后题啊好激动啊,其实知识这题题意比较好理解,然后就试着想了一下,不过还是跪了
576C : http://codeforces.com/problemset/problem/576/C
题意:给你n个点的坐标,然后让你求一条路径,这条路径包含n个点,每个点之间的距离是曼哈顿路径,求出一条路径的长度小于25*10^8
题解:我一开始以为这种题就是排个序,横着搜一遍竖着搜一遍,但是这样找到的肯定不是最优解,而且最优解的话估计要用dp,也许承受不起这个复杂度
看了题解才发现这是个构造题,唉我构造题基本不会,没怎么做过,水的一比
这题是要构造一个解,满足条件,并不需要最优,首先坐标范围是0-10^6,题解很巧妙的把它竖着分成1000个10^3*10^6的长方形,然后每次走完一个长方形再走另一个
奇数个长方形从下往上走,偶数个长方形就从上往下走,只要排序y即可,这样构造的最坏情况,就是1000个长方形走了10^6的y轴距离,x轴的话,在每个长方形里走,用了1000*10^6,还有跨越长方形的花费2000*1000,最坏情况是2*10^9+2000000,完全满足题目条件啊

从此好好练习cf,要有耐心看英文题,开动脑筋,锻炼思维

AC代码 : http://paste.ubuntu.net/12359822/

/***********************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/575/F
这题也是一个挺有难度的题,dp题(dp是必须要日积月累了)
题意:给你一个初始位置,还有n个区间位置,区间里灯亮着,然后你现在可以关灯,你关闭一个区间的花费就是你现在的位置到这个区间的最小值,如果你在区间里,那么就是0花费,你还可以走到区间里,这样关灯就是0花费,但是走的距离就是花费
题解:这题是用dp解决,其实还是很难的,首先就是状态的问题,首先考虑肯定是走到区间的左右端点或者隔空关灯也是在区间端点的位置才能使花费最小,然后就只有1W个点了,所以可以把坐标离散化一下,这样就5000次关灯,10000个点,可以用dp解决
当然这样也许也开不下,所以就用滚动数组dp[2][10005],这样记录前一次和这一次的状态即可,这样表示第i次站在j的位置,关掉第i个区间的灯的最小花费
然后转移就可以从左边或者右边靠近j这个位置
首先从左边靠近,先计算tmp2表示在j位置关灯的花费,然后tmp1记录在j左边的位置关掉i-1个区间之后走到j的位置的最小花费,然后dp[i][j]=tmp1+tmp2
从右边靠近也是这样的道理
最后枚举第n个区间在0-k个位置上的最小值
AC代码 : http://paste.ubuntu.net/12417302/
/********************************************************************************************************************************************************/
http://codeforces.com/contest/545/problem/D
题意:这题其实是个大水题,不过我太二逼了,导致居然过了这么多人的题都做不出。题意是给你一个序列,如果这个数比他前面所有数字的总和大于等于,那么他就是开心的,否则就是不开心,让你重新更改顺序,是开心的人最多
题解:排序,肯定的,然后如果碰到一个人不开心,那么把他扔到最后也不会影响他是否开心,反而会让后面开心的人更多,所以只要碰到不开心的就扔
这种题我居然都没想清楚,还不敢写,真是有够水的,不过必须知耻而后勇,加油

AC代码 : http://paste.ubuntu.net/12417357/

/************************************************************************************************************************************************************/
http://codeforces.com/contest/545/problem/E
题意:求一个源点的最短路树的权值,并且输出是哪些边
题解:30W的数据量,并且spfa不知道如何记录边,dijkstra可以很好的记录边,所以就用dij+heap优化,时间复杂度没问题了,然后就是最短路树,那么不仅要在dis[v]>dis[u]+c的地方进队,还要在dis[v]==dis[u]+c的地方,因为如果相等,这个u的dis肯定比前面更新v的dis更大,说明这个c更小,取得边更小,同样得到最短路,那么最短路树的权值也相应最小,边的话可以用前向星,当前序号除以2来记录
最后注意权值很大,会爆int,需要用LL ,在这里交了两发WA
AC代码 : http://paste.ubuntu.net/12417400/



/************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/571/B
题意:这题是历史遗留问题了,以前一直没有做,现在做了下,方法真是巧妙orz,服了,真心不错,这题交给我们的思维方式,确实不一般
这题求一个序列的这个公式值,然后可以改变顺序,使值最小
题解:这题确实一开始没法上手,其实可以这样发现,i-i+k-i+2k,这样每隔k个
就可以把这些数都分在一组,然后要求这组的相邻差值和最小,那么就是max-min,所以就可以把一开始的序列排序,然后一组一组取,这样就只要关注两端点的差值
然后如何分组呢,可以看出来一共分成k组,可以分成n%k个长度为n/k+1的组(就是最后那些多出来的数,导致一些组的数字比其他组多一个)
还有一些就是k-n%k个长度为n/k的组,然后就可以用递推了,dp[i][j]表示去了i个前一种组,j个后一种组的最优解
然后这会取的最后一个值就是a[i*(n/k+1)+j*(n/k)],max-min就是前面的减去某一组的长度
转移
if(i>=1) dp[i][j]=min(dp[i-1][j]+a[cnt]-a[cnt-l],dp[i][j]);
if(j>=1) dp[i][j]=min(dp[i][j-1]+a[cnt]-a[cnt-l+1],dp[i][j]);

AC代码: http://paste.ubuntu.net/12417460/

/****************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/616/E
题意:求sigma n mod i ,(1<=i<=m)
题解:这题感觉十分之难,光看肯定看不出,复制一发官方题解。

Let's transform the sum . Note that the last sum can be accumulated to only value min(n, m), because for i > n all the values will be equal to 0.

Note in the last sum either  or . Let's carefully accumulate both cases. The first sum can be simply calculated by iterating over all . We will accumulate the second sum independently for all different values . Firstly we should determine for which values i we will have the value . Easy to see that for the values i from the interval . Also we can note that the sum of the second factors in  with fixed first factor can be calculaed in constant time — it's simply a sum of arithmetic progression . So we have solution with complexity .

主要就是式子变形 ,然后就是分类讨论i,因为后面这两个东西的乘积肯定小于等于n,所以先考虑i<=根号n的时候,直接可以枚举算,然后考虑前面那个小于等于根号n的情况,假设它为v,然后可以发现i在一个范围内,n/i都等于这个v,然后可以算出i的范围 范围是这个,左开右闭,然后就能根号n的复杂度内解决问题了
AC代码: http://paste.ubuntu.net/14581637/

/******************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/623/A
题意:给你一个图,然后每个点有a或者b或者c,然后每个字母和它相同的字母或者相邻的连边,a-a,a-b, b-b,b-a,b-c,c-c,c-b这样,然后给你图的边,让你求出这样每个点的字母。
题解:我是太蠢了,以为是dfs就直接写爆搜了,然后不知道哪里写错了,还各种TLE,跪翻,其实做题应该静心仔细想,我感觉我是那种静不太下心来想的人,其实b可以和a,b,c三种连,所以度为n-1的点肯定为b,然后a的肯定都连在一起呢,所以直接搜一次把a的都搜出来,剩下的当作c,然后判断是否可行,所以点和边判一下就好了,以后要静心想,cf不太考很烦的爆搜的
AC代码: http://paste.ubuntu.net/14912541/

好好努力,never give up
/************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/625/D
题意:给你一个数字a,然后导致为ar,a+ar=n,给你n,让你找符合条件的a;
题解:这题就是个思路题,但是比较麻烦,要考虑的有点多,开头自己想的时候只想到首尾开始一起判,但是没想好不同了怎么处理
后来看了题解发现是,首尾开始判i和len-i-1,有几种不同的情况:
1.要么相同,就i++
2.要么前面i比后面len-i-1大1,i位减1,然后给i+1位加10
3.要么前面i比后面len-i-1大11,i位减1,给i+1位加10,然后他比后面第len-1-i位大10,转入下面的判断
4.要么i比len-i-1位大10,那么就是len-i-2要减1,给len-i-1加10,去掉这个进位,然后再判是否相同
每次判完都要回到第一步判,然后就能很清楚的搞定了,其中如果是奇数长度的话,就再判一下中间一位
但是这样并不一定结束了,因为如果你两个长为5的数相加,得到长度为6的数字,你用上面的判法是得不到正确结果的,所以还需要接下去的判断
如果第一位为1,并且长度大于1,就把第一位的1给后一位加上10,然后变为长度减1的一个数,然后在用上面的方法判断,如果还得不到的话就是不存在了
AC代码: http://paste.ubuntu.net/14993324/

/**********************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/623/D
题意:给你n个人,然后你可以抓他们,抓住他们每个人的概率是pi,然后猜他们是谁,如果n 个人都被抓到并且猜对了,游戏结束,问你最小的游戏回合数的期望是多少
题解:贪心,一开始都没理解题意,搞了半天不明白,其实这题是这样,你要求期望小,那么小的回合数的概率应该大,然后有几次应该是你选了某人,但是猜错了他的名字,我不清楚有没有别的做法, 题解上是考虑的猜了第i个人名字ki次,然后sum ki =t(t为游戏回合数),然后sum t*prob(t)=期望
当n回合的时候,肯定是pi相乘,然后考虑第n+1回合,ai为抓住i的概率,bi为没抓住i的概率,ci为所有人名字一共喊了i次并且游戏能在i次以内结束的概率,然后考虑喊了i有ki次,然后喊i这么多次,并且游戏能结束的概率是ci=连乘(1-(1-a[j])^kj),喊了kj次j,并且每次都没抓住j,然后1-这些,等于kj次里面至少一次抓住j的概率,然后连乘,就是i回合里面每个人都至少抓了一次,然后ci-ci-1的话就是正好i回合结束的概率了,然后现在就要考察第i回合应该喊谁能让概率最大,如果是喊x,那么就是乘上(1-b[x]*(1-a[x]))/(1-b[x]);
所以只要遍历n找让这个式子最大的x就行了,然后误差要小于1e-6,看题解说至少30W次,所以遍历30W回合就行了
AC代码: http://paste.ubuntu.net/14993396/
/*********************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/623/B
题意:给你一个序列,然后你可以把其中一段连续的去掉,花费是len*a,也可以把其中几个数字+1或者-1,然后每个数字操作的花费是b,但是不能删去整个数列,求最小花费能让剩余序列的gcd大于1的
题解:首先这题要观察到因为不能全部去掉整个序列,而且去掉只能去一次,而且必须连续,所有左右两个端点必有一个不会被去掉,然后直接把a1,a1+1,a1-1,an,an-1,an+1分解质因数,然后考察整个序列,和哪个因子的时候花费最小就行了(因为只要gcd大于1就行)
开两个数组,p1[i]表示从1-i的用+1,-1操作满足因子为t的时候的花费,p2[i]表示从i-n用+1 -1操作满足的花费,先处理出这些,然后用dp来处理连续的一段是删除还是用+1 -1
ans=min(p2[i]+a*(i-1)+mv),p2[i]是说从i-n用+1 -1,前面用删除,然后mv=min(p1[i]-a*i),就是维护i-1前面这些中这个值最小,然后1-j这一段不删除,j+1-i-1删除,这样就算出了删除的如果在中间或者从开头删的情况,但是还有从后面开始删的情况没考虑
ans=min(p1[i]+a*(n-i))这样就是从后面删的情况
我感觉这题主要要学会发现为啥题目给了不能全部删去,还有就是删除中间一段的这个dp操作,我dp太烂了,这种操作一直写不好
AC代码: http://paste.ubuntu.net/14993458/

/**************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/613/C
题意:给你一个n,告诉你有n种字母,然后告诉你每种字母有ai个,然后要你构成一个项链,然后剪开来能得到回文串的最大方法
题解:因为剪开来是回文串,所以如果奇数个数的珠子如果大于1的话,剪开来肯定不能得到回文,然后如果能构成回文,那最多有多少种方法呢,方法就是所有ai的gcd,很明显吧,因为ai的话有ai个剪得地方,然后有n个ai,所以就是gcd
然后就是输出了,因为奇数是比较特殊的,所以如果只有1种切法,那么可以分成左右两半,然后中间夹着一个奇数,所以可以先分成2*gcd段,构造一段,然后偶数就是除以2*gcd,里面随便放就行了,奇数是先减去gcd然后除以2*gcd,然后输出时,先正着输出,夹着个奇数的,然后倒着输出,然后这样循环gcd次,如果没有奇数,中间就不加奇数
AC代码: http://paste.ubuntu.net/15271959/

/***************************************************************************************************************************************************************************************/
http://codeforces.com/contest/629/problem/C
题意:给你一个s串,括号,然后前面加个p串,后面加个q串,得到的p+s+q,里面(和)数量相同,然后对于每个前缀,(的数量都大于等于 )
题解:先对后面的q串进行dp预处理,dp[i][j]表示还有i个(和j个)的时候的方法
然后对前面p串进行dp,dp[i][j]=dp[i+1][j]+dp[i][j+1]+(q[a][b]),后面加的这个是当i-j满足大于等于s串里面)减去(的最大值
AC代码: http://paste.ubuntu.net/15271979/

/**************************************************************************************************************************************************************************************/
http://codeforces.com/contest/629/problem/D
题意:给你n个蛋糕的尺寸,然后j蛋糕可以放在i蛋糕上面,满足j>i,Vj>Vi,问你得到的最大体积是多少
题解:先给蛋糕体积排序,体积相同就大的序号在前,然后开个线段树存当前区间最大体积是多少,然后就线段树搞搞就好了
AC代码: http://paste.ubuntu.net/15271993/

/************************************************************************************************************************************************************************************/

 http://codeforces.com/problemset/problem/626/F
题意:给你n个数字,让你分成若干组,每组的不平衡值为组里面最大的数字减去最小的数字,一个数也可以单独为一组,然后这组的不平衡值为0,问你所有组不平衡值小于等于k的分法有多少种
题意:这题好难啊,首先应该想到是dp,就是对于每一个数字,他应该是一组的开头,或者中间,或者结尾,中间的话可以算是自成一组然后放在中间或者外面
然后我就考虑n^2*k复杂度的dp,但是每次考虑这个点是结尾的时候再去算不平衡值,然后统计个数很复杂啊,怎么搞都搞不出来
看了厕神的方法,首先这题要设当前有j个组,然后第i个放进去,是放j个组其中,还是自成一组的开头,还是关闭一个组,有三种转移,于此同时,需要在每次转移的时候都计算不平衡度,这就需要用到提前消费的思想,比如这会有j个组,然后放a[i],就要把a[i]-a[i-1]的不平衡度给每个组都加上,然后下一次放a[i+1]的时候,就能消掉。
虽然我不是很确定这样提前消费会不会爆总的不平衡度上限,但是这样是可以过题的otz
AC代码: http://paste.ubuntu.net/15341076/
/************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/626/E
题意:给你n个数字,然后让你取一些构成一个集合,要求是集合里的平均值减去中位数要尽可能大,问你取多少个,和每个分别是什么
题解:首先这题看见了也是无从下手,需要发现一个性质,就是集合里肯定要奇数个,为什么呢,其实我也不是很明白,就这么想吧,如果是偶数个,去掉比中位数大的那个数,中位数下降比平均数多。。。
Let’s fix the median at xi (in the sorted list), and set the size of the set to 2j + 1. We’d like to maximize the mean, so we can greedily choose the largest j elements below the median and the largest j elements above the median: xi - j, ..., xi - 1 and xn - j + 1, ..., xn.
sorted!!!!!!!!!!!!!!!!!!!!千万不要忘记排序,因为在两边取的时候应该是使用三分(因为两边取的时候肯定是有可能先递增后减,或者是先减后增这样的,所以需要先排序,不然就不能确定只有一个极值点了!!!!因为这个错了好久)
为什么呢 sum[x]-sum[x-r-1]+sum[n]-sum[n-r],如果不排序,你能确定这个值在长度递增的时候是递增的么(不能把,我真是chun)
然后就是三分了,三分的话是要写自己习惯的写法,我开头写对的,但是因为没排序,导致一直wa,后来抄了一半别人的三分,还是错otz
如果是整点的三分以后就用这个写法了orz
AC代码; http://paste.ubuntu.net/15341084/

/************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/651/E
题意:给你一个矩阵,然后按照矩阵里原来的大小顺序,设计一个新的矩阵,让矩阵里最大的值最小
题解:大小关系的话就是拓扑关系,所以类似拓扑排序肯定是要的,但是里面有些值大小是相同的,如果建立拓扑关系的话100W点,最好就相邻的建一条边还能承受,如果有相同的,就很烦了,所以首先需要并查集,把行列里相同的都并起来,然后建边,拓扑排序一下,最后输出就OK了,并不是很难,但是没想到并查集我还是太弱了啊
AC代码: http://paste.ubuntu.net/15341141/

/************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/631/D
题意:给你两个字符串,但是这个字符串的话,十分之长,有连着l个同一个字符,然后l有100W,求第二个字符串在第一个里面出现多少次啊
题解:字符串匹配问题嘛,肯定是KMP啦,就是个结构体的KMP,然后先需要把相邻一样的字符的l给合并了,然后kmp呢,不太好k,因为b串两端的字符在a串里匹配可能比a串里那一块少,但是也是能匹配的,所以就需要先把b串左右两端减掉(如果长度是1和2就直接遍历判断吧),然后拿中间的去a串里做kmp,找到的时候,就判一下左右两端,是不是a串里两端的l都大于等于b串的两端,就可以了
这题我wa的一个地方就是kmp b串的长度是len,就必须是len,我自以为规定他长度len,但是用的串其实长度是len+1,然后wa
一定要另外开个数组搞
AC代码: http://paste.ubuntu.net/15341166/

/**************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/628/D
题意:让你求一个能被m整除的,偶数位为d的数字的个数,在[a,b]之间
题解:数位dp咯,但是这题有个坑点就是前导0,需要记录的几个状态也就是剩余长度,当前是奇数偶数位,余数,是否是边界,是否有前导0
然后我跪了好久是因为,给dp赋值和返回的时候,应该要先判断当前前面不是前导0,我没判断,跪了好久,后来好不容易才发现了枸蒻了
AC代码: http://paste.ubuntu.net/15341184/

/************************************************************************************************************************************************************************************/
http://codeforces.com/problemset/problem/632/D
题意:最长串lcm小于等于k
题解:唉这种题我居然当时都不会做,因为m只有10^6,所以可以直接枚举每个数的倍数,用数组标记,然后找到下标最小的值最大的就行了
先排序离散化,所以复杂度是n+n/2+n/4+...=2n
唉水题啊我居然都秀逗了
AC代码: http://paste.ubuntu.net/15341216/

最近经常犯水题反而想复杂不会做的毛病,是不是得治啊!!!

/*****************************************************************************************************************************************************************************************/
http://codeforces.com/contest/653/problem/E
题意:给你一棵树,然后给你m个限制,是a和b之间不能有边!然后告诉你点1正好连着k个边,问你能还原树么
题解:点1的限制先不考虑,可以先考虑是否能构成树,就是连通,然后连通也不太好判,因为有很多的边啊,所以你需要开个set记录不能有的边,然后开个set记录还没找的点,然后从1开始在还没找的点里面找可以连的,然后dfs下去,删删删,然后看能否连通
连通了之后就是判能和1相连的是否大于等于k,还有就是k是否大于等于剩下的点最少能够构成的连通块,为什么呢,因为首先一些点是只能和1相连,然后我一开始以为剩下的点都能连成一块,然后一直跪,后来发现其实不是,比如a,b连起来和1相连,c不是只能和1相连的点,d也是如此,然后c,d都不能和a,b相连,只能c,d之间互相相连,所以需要求最少的连通块,然后k大于等于它,这个计算可以在搜的时候一起记录
AC代码: http://paste.ubuntu.net/15455291/





你可能感兴趣的:(ACM,codeforces)