Codeforces 1270 Goodbye 2019 (C,D,E,F,G)

C - Make Good

s u m sum sum为所有数的异或和, t o t tot tot为所有数的和。 t o t tot tot显然必须是偶数。所以如果 t o t tot tot是奇数的话,就先往数组里面加入一个 1 1 1

如果 2 × s u m > t o t 2\times sum > tot 2×sum>tot,就往数组里面加入两个 2 × s u m − t o t 2 {2\times sum - tot \over 2} 22×sumtot,这对数组中的数的异或和没有影响。

否则,先加入一个 2 58 2^{58} 258(一个很大的 2 2 2的整数次幂),然后就会转化成 2 × s u m > t o t 2\times sum > tot 2×sum>tot的情况。

如果又要加入 1 1 1又要加入 2 58 2^{58} 258,可以直接加入数 1 + 2 58 1+2^{58} 1+258,这样就可以满足加的数至多是三个的限制。

Code

D - Strange Device

首先考虑 k = n − 1 k=n-1 k=n1怎么做:可以把每个大小为 n − 1 n-1 n1的子集都问一遍,这样第 m + 1 m+1 m+1小的会出现 m m m次,第 m m m小的会出现 n − m n-m nm次,根据出现过的元素的大小关系以及它们分别的出现次数就可以推出 m m m

n > k + 1 n>k+1 n>k+1,直接对前 k + 1 k+1 k+1个元素通过上面的方法计算就可以了。

Code

E - Divide Points

将点分成四组: A 0 , 0 , A 0 , 1 , A 1 , 0 , A 1 , 1 A_{0,0},A_{0,1},A_{1,0},A_{1,1} A0,0,A0,1,A1,0,A1,1。点 ( x , y ) (x,y) (x,y)属于组 A x ( m o d 2 ) , y ( m o d 2 ) A_{x\pmod 2,y\pmod 2} Ax(mod2),y(mod2)。用 P , Q P,Q P,Q代表最后分得的两个点集。

若所有点都属于同一个组,则将所有点的坐标除以 2 2 2(如果原数是奇数,则向下取整)之后再做,与原问题等价。

如果 A 0 , 0 ∪ A 1 , 1 A_{0,0}\cup A_{1,1} A0,0A1,1非空,且 A 0 , 1 ∪ A 1 , 0 A_{0,1}\cup A_{1,0} A0,1A1,0非空,令 P = A 0 , 0 ∪ A 1 , 1 , Q = A 0 , 1 ∪ A 1 , 0 P=A_{0,0}\cup A_{1,1},Q=A_{0,1}\cup A_{1,0} P=A0,0A1,1,Q=A0,1A1,0即可。【同一组内的点的 ( x + y )   m o d   2 (x+y)\bmod 2 (x+y)mod2相同】

否则,若 A 0 , 0 ∪ A 1 , 1 A_{0,0}\cup A_{1,1} A0,0A1,1为空集,令 P = A 0 , 1 , Q = A 1 , 0 P=A_{0,1},Q=A_{1,0} P=A0,1,Q=A1,0即可。【只有同一组内的点的 ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 (x_1-x_2)^2 + (y_1-y_2)^2 (x1x2)2+(y1y2)2 4 4 4的倍数】

否则 A 0 , 1 ∪ A 1 , 0 A_{0,1}\cup A_{1,0} A0,1A1,0为空集,令 P = A 0 , 0 , Q = A 1 , 1 P=A_{0,0},Q=A_{1,1} P=A0,0,Q=A1,1。【同上】

Code

F - Awesome Substrings

x = L c n t x = {L\over cnt} x=cntL,其中 L L L表示子串的长度, c n t cnt cnt表示子串内 1 1 1的个数。设 T T T为某个定值。

a i = ∑ j ≤ i [ s j = 1 ] a_i = \sum_{j\le i} [s_j = 1] ai=ji[sj=1]

将答案分为两部分计算;

  1. x ≤ T x\le T xT:枚举每一个 x x x,然后枚举子串右端点 r r r,则左端点应满足 r − ( l − 1 ) a r − a l − 1 = x ⇒ r − a r x = l − 1 − a l − 1 x {r-(l-1)\over a_r-a_{l-1}} = x\Rightarrow r-a_rx = l-1-a_{l-1}x aral1r(l1)=xrarx=l1al1x,直接用map或者hash_table统计一下即可。
  2. x > T x> T x>T,显然有 c n t = L x ≤ n T cnt = {L\over x} \le {n\over T} cnt=xLTn,所以可以枚举子串的左端点和 c n t cnt cnt,此时要求右端点必须落在某个区间内且 r − l + 1 ( m o d c n t ) r-l+1 \pmod {cnt} rl+1(modcnt) 0 0 0,可以 O ( 1 ) O(1) O(1)计算这样的右端点的数量。

如果用map,时间复杂度 O ( n T log ⁡ n + n ⋅ n T ) O(nT\log n + n\cdot {n \over T}) O(nTlogn+nTn),当 T T T n log ⁡ n {\sqrt{n\over \log n}} lognn 的时候复杂度最优,为 O ( n n log ⁡ n ) O(n\sqrt {n\log n}) O(nnlogn )

Code

G - Subset with Zero Sum

Sol

i − n ≤ a i ≤ i − 1 i-n\le a_i \le i-1 inaii1等价于 1 ≤ i − a i ≤ n 1\le i - a_i \le n 1iain

i i i i − a i i-a_i iai连边,会得到基环内向树森林。取一个环上的所有元素:

x − a x = y y − a y = z ⋮ u − a u = x x - a_x = y \\ y - a_y = z \\ \vdots \\ u - a_u = x xax=yyay=zuau=x

将所有式子加起来,会得到 a x + a y + ⋯ a u = 0 a_x+a_y+\cdots a_u = 0 ax+ay+au=0

Code

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值