codeforces 789 div2 题解

被闹钟叫醒再睡过真是心塞,只好熬得更晚刮完div2作补偿.......


AB就略了吧,B稍稍有点恶心但也是代码题


C的话是可以预先处理出差分后的绝对值序列,然后发现实际上就是求这个序列的最大子段和,基础dp知识


D有点意思,要分两部分来算,一部分是自环,另一部分是其他边,发现自环集合里随便取两个作为只经过一次的都是可行的,所以是C(num,2),这个显然;对于其他边来说,选出的两条边可行当且仅当这两条边有公共顶点,那就枚举公共顶点,sigma C(out,2)即为这部分答案,原因:

a.若两条边有公共顶点,那就可以从两条边某个非公共顶点出发,对于其他路径走去走回,对于这两条边所在路径走去回时到两条边另一个非公共点终止

b.若无公共顶点,路径必须经过这四个顶点而保证这两条边只经过一次,显然不成立,因为要使某条边不被经过,必须是路径的端点在这条边端点处。

还有一部分答案,是这两条边,一条是自环,另一条是其他边,这个就显然了,所以再加num*(n-num)



E这有点玄学.....那个m的范围是吓人的,ai只有1000种取值,所以m可以缩小到<=1000

化简一下式子,发现实际上是要 (p1*a1+p2*a2...pm*am)/k=n ,k=p1+p2....+pm

将k乘到右边,变成: (p1*a1+p2*a2+...+pm*am)=k*n,将每一个n都减到左边,就变成了:

a1*(p1-n)+a2*(p2-n)+....+am*(pm-n)=0

所以构建b序列bi=ai-n,开始玄学bfs......

直接bfs显然过不了,怎么办???

发现若当前的sum>2000,此时想要到达0,就要在之后减掉-sum,而-sum<-2000,不可能只减去某一个ai达到目标,式子为 sum-ai-aj-ak-....=(ai'+al'....)-aj-ak....=0,那么完全可以将上式变成:

ai'-aj+al'-ak....=0,使得每一个前缀和sum'<=2000,所以当sum>2000时剪枝

又因为正+负等价于负+正,所以当sum'<0,剪枝 


代码:

A:http://paste.ubuntu.com/24277232/

B:http://paste.ubuntu.com/24277238/

C:http://paste.ubuntu.com/24277245/

D:http://paste.ubuntu.com/24277246/

E:http://paste.ubuntu.com/24277247/

你可能感兴趣的:(codeforces)