[杂题笔记]2021.08.18-2021.09.03,CF#741 Div.2&CF#736 Div.2&CF Global Round15&CF#739 Div3
2021.08.18-2021.09.03
【CF#741 Div.2】
https://codeforces.com/contest/1562/problem/A, (这A题好难)给你\(l,r\),问最大可能的\(a\bmod b\)(\(l \leq b\leq a\leq r\))。
先是想要让\(a=b-1\),但\(a\geq b\),然后就想着取\(l\leq b\leq a=2b-1\leq r\),右边得到\(b\leq \lfloor\frac{r+1}{2}\rfloor\),左边就是条件\(l\leq\lfloor \frac{r+1}{2}\rfloor\),而仔细想想,对于\(l\geq \lfloor \frac{r+1}{2}\rfloor\)的情况,直接取\(b=l,a=r\)就行。
第一题好难。
https://codeforces.com/contest/1562/problem/B, 给你一个数位可以很长的数(且不包括数位0),删掉尽可能多的数位,使得剩下的数字not prime,输出剩下的数(保证存在答案)。
这题限制挺宽的,最好的情况就是剩一个1,4,6,8,9,所以如果有就直接输出,不然的话如果有2个\(\{2,3,5,7\}\)也很好,再不然说明\(2,3,5,7\)都最多只有一个,暴力搜一下。
https://codeforces.com/contest/1562/problem/C, 给一个二进制串,要你找\((l_1,r_1),(l_2,r_2)\):
- 区间长度超过\(n/2\)
- 两个区间不完全相同
- 存在一个\((l_1,r_1)\)的子串\(s\)和\((l_2,r_2)\)的子串\(t\),使得\(s\)的十进制数是\(t\)的倍数。
有点像脑筋急转弯,首先是“xxxxx0”可以写成"xxxxx"的两倍,以及"0xxx"和"0xxx"是一样的,所以有0就直接找,否则就是全都是1的情况,注意\((2^k-1)|(2^{km}-1)\)的,靠着这个性质,全1的情况取\(len=n/2\),区间取\([1,len],[1,2len]\)即可(看了下题解我还想多了,直接用\([1,n-1],[2,n]\)就行了吼)。
https://codeforces.com/contest/1562/problem/D2, 题意懒得翻了。
首先我是先想\([1,n]\)的询问怎么做,记\(s(l,r)\)是\((l,r)\)的sign-variable sum,那删掉\(x\)就会导致\(S=s(1,n)\)变成\(s(1,n)\pm a_x -2s(x+1,n)\),奇偶性改变!进一步推出删2个奇偶性不变,以及删2个的情况可以通过删第一个转变成奇数的情况,所以我们就只考虑奇数的情况:
\(n\)是奇数则\(S\)也是奇数,如果删掉第一个元素,就变成是\(S\pm 1\),如果删掉最后一个就变成\(-S\pm 1\),这两个东西要么有一个是0(此时\(|S|=1\)),否则\(|S|>1\),两个一定异号,而如果删\(x\)的sum变成删\(x+1\)的sum,这里sum的变化是\(\pm(a_x+a_{x+1})\in{0,-2,2}\),类似介值定理的东西告诉我们这里一定有零点。
上面这个思路就能比较简单地解决第一问D1:如果区间和是0就直接0,否则奇数1偶数2。
而对于第二问偶数2的情况,也可以通过删一个\(l\)来变成奇数的情况(因为上面的分析,一定是有解的)。具体找位置就用二分:虽然不单调,但找零点还是可以的。QAQ记得特判一下\(l=r\)的情况。
【CF#736 Div.2&CF#736 Div.1】
https://codeforces.com/contest/1549/problem/A, 给一个素数\(p\geq 5\),找到任意一组\(a,b:p\bmod a=p\bmod b,(a<b\leq p)\)。
注意\(p\geq 5\),直接取\(a=2,b=p-1\)即可。(翻了翻我当时的代码,当时没看到题目说素数,多一个偶数的情况就是取\(a=2,b=p\))。
https://codeforces.com/contest/1549/problem/B, 一个象棋棋盘,两行,第一行给出地方pawn的位置,第二行是你的pawn的位置,假设你的兵在\((i,j)\),它可以跳到\((i-1,j-1)\)或者\((i-1,j+1)\)(如果目标位置有敌兵),或者如果\((i-1,j)\)是空的,可以直接走到\((i-1,j)\),问有多少个pawn能走到第一行。
一个小贪心,从左往右扫一遍,按照左中右的顺序跳。
https://codeforces.com/problemset/problem/1548/A, 第\(i\)个人的power是\(i\),三种操作,\(u,v\)连一条边,删去\(u,v\)的边,以及询问:对于每个人\(x\),所有和他连边的,如果有比他大的,就淘汰掉\(x\),一直操作直到没有人被淘汰。
容易猜到一个性质:一个人能活下来当且仅当,\(x\)比所有和他连边的人都要大,否则一定是一连串地删人。然后这题因为保证没有重边,就可以维护每个结点的度数,以及有关系的、比他小的结点的个数,就可以线性地实现这个。
https://codeforces.com/problemset/problem/1548/B, 给一个序列,问最长能找多长的一个子段\([l,r]:\exist m>1:a_l\bmod m=a_{l+1}\bmod m=\dots=a_r\bmod m\)。
一开始卡在第一步惹,其实就是如果真的去考虑模数好像没法考虑,复杂度降不下来,稍微转个弯去想差分,约束就可以等价成\(a_{l+1}-a_{r}\equiv a_{l+2}-a_{l+1}\dots(\bmod m)\),也就是\(\gcd(a_{l+1}-a_l,\dots,a_{r}-a_{r-1})>1\),\(gcd\)有单调性,静态区间GCD本质就是个区间min,可以用ST表维护,枚举左端点二分右端点就行。
这题的复杂度很有意思,看起来是\(O(n\log n \log M)\)(\(M\)是值域),因为我们之前说求\(gcd(a,b)\)的复杂度是\(O(\log(\min(a,b)))\)的,但其实有更紧的界\(O(\log (\min(a,b)/\gcd(a,b)))\)——因为求\((a,b)\)和求\((a/(a,b),b/(a,b))\)的操作次数其实是一样的。
对数里的除法变成减法,这个性质就会导致你在求一段东西的gcd的时候,\(O(n\log M)\)这个东西会变成\(O(n)\),直观感觉就是gcd是越求越小的,代价也是越来越低。
https://codeforces.com/problemset/problem/1548/C, 抛开描述题面,其实对每个\(x\),求\(C_3^x+C_6^x+\dots C_{3k}^x\),\(n\leq 10^6\)。
首先是一个性质,\(\sum_{k=0}^n\binom{k}{x}=\binom{n+1}{x+1}\):右边是从\(n+1\)个物品选出\(x+1\)个物品的方案数,左边看成是在枚举选出物品标号的最大值是\(k+1\)(从1开始),再从剩下\(k\)个物品选\(x\)个的方案数。
然后就可以dp:记\(dp[x][j]\)表示\(\sum_{k=0}^{n}\binom{3k+j}{x},(j=0,1,2)\)。那么\(dp[x][0]+dp[x][1]+dp[x][2]=\sum_{k=0}^{3n+2}\binom{k}{x}=\binom{3n+3}{x+1}\),以及由\(\binom{n}{m}=\binom{n-1}{m-1}+\binom{n-1}{m}\)就有\(dp[x][1]=dp[x-1][1]+dp[x][0]\)和\(dp[x][2]=dp[x-1][2]+dp[x][1]\),就可以递推出所有的\(dp[][]\)了。
【CF Global Round15】
https://codeforces.com/problemset/problem/1552/A, 把字符串排序好得到\(t[1,\dots,n]\),把\(str[i]\neq t[i]\)的抽出来就行。
https://codeforces.com/problemset/problem/1552/B, 虽然在这里可能会存在\(a<b,b<c\)但是\(a>c\)的情况,但我们依然可以重载小于号,从左到右取max,如果\(x\)符合答案的条件,一定会被取到,同时再check一边是否比别的都要大就行。
https://codeforces.com/problemset/problem/1552/C, 卡了许久,题目有一句话很关键:o point strictly inside the circle belongs to all 3 chords.也就是只要有交叉就会多一个交点,不用管三线共点的情况。于是可以证明,最优的染色方法是把剩下的\(2(n-k)\)个点拎出来重新标号,然后按照第\(i\)个点连接\(i+(n-k)\)来连线(假设原本是\(a-b,c-d\)这样没有交叉的连接,如果换成\(a-c,b-d\)这样有交叉的连法,交点至少不会变少)。
https://codeforces.com/contest/1552/problem/D, 给一个\(a[1,\dots,n]\),问是否存在\(b[1,\dots,n]:\)对所有\(a_i\)存在\(1\leq j,k\leq n:a_i=b_j-b_k\),这题\(n\leq 10\)。
\(n\)只有10看着就很乱搞…首先\(b\)的一个差分一定能搞定一个\(a_i\),所以\(n\)个位置至少能解决\(n-1\)个\(a_i\),问题就是剩下一个怎么搞定。
如果\(a_i=0\)或者\(a_i=a_j\),就可以少用一个\(b\)的代价,这时候一定是YES,进一步,只要能找到\(a[1,\dots,n]\)的一个子序列\(\pm a_{p_1}\pm a_{p_2}\dots\pm a_{p_k}=0\)就行,当然这只是充分条件,但我们猜他必要,于是\(O(n3^n)\)暴力枚举试着交一发,过了,好那他就是必要条件了(bushi)。
[必要性]假设存在符合条件的\(b\)数组,考虑张\(n\)个点的图,每个点的点权是\(b_i\),接着因为每个\(a_i\)都能写成\(b_{j_i}-b_{k_i}\)的形式,我们连一条\((j_i,k_i)\)的边权为\(a_i\)的边,这样就构成了一个\(n\)个顶点\(n\)条边的图,\(|V|=|E|=n,|V|+|F|-|E|=2\),此时一定有环(此时先不考虑方向),而这个环上:
\(\begin{aligned}(b_{v1}-b_{v2})+(b_{v2}-b_{v3})+\dots+(b_{v_{k-1}}-b_{vk})+(b_{vk}-b_{v1})=0\end{aligned}\)
我们说每条边对应一个\(a_i\),那这个式子就意味着\(a[1,\dots,n]\)的一个子序列\(\pm a_{p1}\pm\dots\pm a_{pk}=0\),也就是我们前面的充分条件。
【CF#739 Div3】
https://codeforces.com/problemset/problem/1560/A, 暴力
https://codeforces.com/problemset/problem/1560/B, 因为是一个圈,一定有\(a+n/2=b\)或\(b+n/2=a\)之一。
https://codeforces.com/problemset/problem/1560/C, \(O(\sqrt k)\)地求出在哪一层。
https://codeforces.com/problemset/problem/1560/D, 假设当前的串是\(s\),要变换成目标串\(t\),因为只能在\(s\)的后面加东西,所以我们就找一个尽可能长的\(s\)的前缀\(pre\),使得它和\(t\)的一个子序列一样,这样就得到最小操作次数\(|s|+|t|-2|pre|\),再枚举答案是2的多少次幂即可。
https://codeforces.com/problemset/problem/1560/E, (这题感觉有点小码),思路很简单,先倒着从\(t\)里找还没出现过的字符,加到order
里,最后order
翻过来就得到删除的顺序,然后再用每个字符的出现次数算\(s\)的长度,从\(|t|\)里截取前\(|s|\)个字符就是\(|s|\),但这还不够,再把\(s\)和order
代回去验证一下会不会得到\(t\)…。
https://codeforces.com/problemset/problem/1560/F2, dfs/数位dp?