ZROI 19.08.08模拟赛

传送门

写在前面:为了保护正睿题目版权,这里不放题面,只写题解。


首先恭喜swk今天翻车!

“小心大样例演你。”——天祺鸽鸽

果然swk今天被大样例演死了,天祺鸽鸽诚不欺我!


  • A

这题标程是前几天ACM赛的双栈背包……

然而可以排序之后直接背包,(O(nm))随便过(


  • B

菜 swk 菜

发现答案就是子串中最长border,即串长减去最短循环节。

每个字母是独立的,可以分开计算答案。

对第(i)个字母,设循环节循环次数为(k),在循环节内的长度为(f_i),剩余的长度为(g_i),则存在(f_icdot k+g_i=c_i),此时(i)对答案的贡献为(f_i (k-1)+min(f_i,g_i))

(40pts:)

有一个假做法在(n=2)时是对的,但是陈主力也不知道为什么。

考虑枚举(k)。直觉想到可以贪心地令(f_i)最大,即(f_i=lfloorfrac{c_i}k floor)

然而在(n>2)时就会出锅。

反例大概是(kleq 3)时,贪心的使(f_i)最长,会因为第一个循环节被剪掉导致答案变小。

(70pts:)

仍然要枚举(k),但是需要确定(f_i)的最优取值。

分两种情况讨论:(f_i< g_i)(f_igeq g_i)

第一种情况,(ans=f_icdot k),即(f_i<g_i)时,(f_i)越大越优。

此时有(f_i<g_i=c_i-f_icdot k),移项得(f_icdot (k+1)<c_i),即(f_i=lfloorfrac{c_i}{k+1} floor)时最优。

第二种情况,(ans=f_icdot (k-1)+g_i)

考虑在保持(f_igeq g_i)的情况下,令(f'_i=f_i-1),则(g'_i=c_i-f'_icdot k=c_i-(f_i-1)cdot k=g_i+k),代入上式得(ans'=(f_i-1)cdot (k-1)+g_i+k=f_icdot (k-1)+g_i+1=ans+1)

我们惊喜地发现,使(f_i)减小之后,(ans)增大了。即(f_igeq g_i)时,(f_i)越小越优。

此时有(f_icdot(k+1)geq c_i),即(f_i=lceilfrac{c_i}{k+1} ceil)时最优。

枚举(k),对每个(k)取两个值计算。复杂度(O(max(c_i)cdot n))

(100pts:)

发现对于每个有若干互不相交的([l_i,r_i]),使得对于任意(k_iin [l_i,r_i],jin [1,n])(lfloorfrac{c_j}{k_i+1} floor,lceilfrac{c_j}{k_i+1} ceil)的值是相等的。

这启发我们使用整除分块,对每个区间只算一次。由某些数论知识可知,这样的区间最多只有(O(sumsqrt {c_i}))个。时间复杂度(O(ncdotsumsqrt{c_i}))


  • C

(10pts:)

取反、左移、右移。

(25pts:)

位运算实现a+b:xor,and,左移(1)位,递归即可。

(40pts:)

把每一位取出来之后直接加,最多迭代(6)次即可。

(65pts:)

发现将(x) xor (y)的最高位提取出来就可以解决。

(x) xor (y=a) ,对于(iin [1,log_2 64)),执行(a |=(a>>2^i))

如此操作后,(a)的最高位以下的位全都赋为了(1)。xor一下就好了。

(80pts:)

做法类似上个子任务,方向反过来即可。需要卡一卡常数。

(100pts:)

发现需要实现(min(x,y))

(min(x,y)=[x<y]cdot x+[xgeq y]cdot y),发现需要实现一个数乘以(0/1)。等价于and上 (0/2^{64}-1),用子任务(4)的方式解决即可。

原文地址:https://www.cnblogs.com/suwakow/p/11375086.html